//服务端，用于调用数据库数据，并返回结果

 
var express = require('express');
const multer = require('multer');
const xlsx=require('xlsx');
var bodyParser=require('body-parser')
const fs=require('fs');
var app = express();

var urlencodedParser=bodyParser.urlencoded({extended:false}); 
var url=require('url');//小程序解析URL用途

//定义MYSQL数据源，直接连接。
//另外可以用连接池 pool=mysql.createPool();在连接时用pool.getConnection(function(err,conn){  conn.query(*); conn.release() })
var mysql=require('mysql');
const { resourceLimits } = require('worker_threads');

 
 //直接取表数据查询  ---测试直联
app.get('/sysparam_mysql',function(req,res){    
    var connection=mysql.createConnection({
   host:'localhost',
   user:'root',
   password:'sn123456',
   database:'mes_basis'
    });
    connection.connect();
    connection.query('select * from base_sysparam',function(err,results){
    if(err)
        res.send(err);
    var j={success:'ok',data:results};
     res.json(j);   //返回JSON，OK  ，  也可以直接用res.send(),默认会作处理
   });
   connection.end();
});

//执行存储过程，带参数返回数据  -------测试存储过程，带参数
app.get('/basis_api/sysparam/:icode',function(req,res){
var connection=mysql.createConnection({
host:'localhost',
user:'root',
password:'sn123456',
database:'mes_basis'
});
     connection.connect();
     var sql='call proce_sysparam(?)';   //用占位符？时，会自动防止SQL注入
     var opt=[req.params.icode];   
     //req.params取GET路径直接参数，req.query取GET路径带名称参数（如表单GET），
    //req.body取POST，则为req.body.p---需引入body-parse解析

      connection.query(sql,opt,function(err,results){
         var j={success:'ok',data:results};
         res.send(j);
   
    //NODE和普通JS语法是通用的：数组遍历
       results.forEach(function(r){
           console.log(r);
          });
     });
    connection.end();

});

//测试简单的IP连接---------------------------------------------
app.get('/', function (req, res) {
   res.send('Hello World'+req.hostname+'*'+req.originalUrl+'***'+req.ip);
 })

//测试与antd前端的连接
app.get('/basis_api/test',function(req,res){
   res.send('Congaratuation,It is work!!-------------');
})


//通过数据连接池连接----可以在定义一个数据连接模块，通过require引入--------测试数据池连接------------------前后端系统对接示例----------------
//注意：单个连接每个都要创建mysql.CreateConnection()+end，
//而连接池在一次mysql.createPool后，只需每次通过pool.getConnection()+release;
 var pool=mysql.createPool({
        host:'localhost',
        user:'root',
        password:'sn123456',
        database:'htoms2',
        charset:'utf8mb4',
        connectTimeout:1000000,
       });

//带参数连接。
//直接包含在路径中的，用[req.params.xxx]，在路径？X=Y后的，用[req.query.xx]，在BODY中的(传过来时为data:参数对象)，用req.body.xx
app.get('/basis_api/sysparam/pool/:icode',function(req,res){
    
       var sql='select * from base_sysparam where item_code like concat("%",?,"%")';
       var opt=[req.params.icode];
       pool.getConnection(function(err,conn){
             if(err)  console.log('连接池错误。。。。。');
             else
              console.log('连接池成功。。。。');
         conn.query(sql,opt,function(err,results){
//返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:'ok',data:{success:true,data:results}};  
              console.log(j);
              res.send(j);
         });
         conn.release();
    });
   
  });


//测试由前台传过来的参数数据更新----------------------------------------------------------------------------系统参数------------
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());

app.post('/basis_api/sysparam/update',function(req,res){//---1
    //var d2=req.body.paramm;
    var d2=req.body.paramm;
    console.log('JSON输出：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
  //  res.send({data:'成功更新数据'});
    var sql='call proce_updatesysparam(?)';
    var opt=[JSON.stringify(d2)];                  //---------转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
    pool.getConnection(function(err,conn){   //--2
        if(err)
          console.log('连接池错误');
        else
         console.log('连接数据库成功');
       
    conn.query(sql,opt,function(err,results){   //执行SQL--3
        if(err){
           console.log(err);
         res.end(JSON.stringify({success:'error'}));
       }
        else{//--4
                  
        res.end(JSON.stringify({success:'ok'}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
          console.log('数据库更新成功，恭喜');
        }//--4
   });//--3
    conn.release(); 
  } );//连接池结束--2
   

  });//--1


//创建树形结构数据的迭代函数，此处为接收“区域”数据，并生成符合TREE字符串格式返回------------------------
function buildTree(rets){
    //最大5层，先分拆为5个数据集，再逐个生成
        var t0=[];
        rets.map((r)=>{
                   if(r.higher_code.length===0&&r.status===1)
                       t0.push(r);
                      return;
              });

         var t1=[];
        rets.map((r)=>{
                   if(r.higher_code.length===1&&r.status===1)
                       t1.push(r);
                      return;
              });
var t3=[];
        rets.map((r)=>{
                   if(r.higher_code.length===3&&r.status===1)
                       t3.push(r);
                      return;
              });
var t5=[];
        rets.map((r)=>{
                   if(r.higher_code.length===5&&r.status===1)
                       t5.push(r);
                      return;
              });
var t7=[];
        rets.map((r)=>{
                   if(r.higher_code.length===7&&r.status===1)
                       t7.push(r);
                      return;
              });
var t9=[];
        rets.map((r)=>{
                   if(r.higher_code.length===9&&r.status===1)
                       t9.push(r);
                      return;
              });
//逐个生成数组对象
var ctree=[];
ctree[0]={key:t0[0].code,title:t0[0].code.concat('  ',t0[0].name),children:[]};
//第一 层
t1.map((t)=>{
     ctree[0].children.push({key:t.code,title:t.code.concat('  ',t.name),children:[]});
});
//第三层：需要先定位，再插入
 t3.map((t30)=>{
     ctree[0].children.map((c3,index)=>{
         if(t30.higher_code===c3.key)
                  ctree[0].children[index].children.push({key:t30.code,title:t30.code.concat('  ',t30.name),children:[]});
      })
})
//第五层：
 t5.map((t50)=>{
     ctree[0].children.map((c51,index1)=>{
             ctree[0].children[index1].children.map((c53,index3)=>{
                   if(t50.higher_code===c53.key)
                        ctree[0].children[index1].children[index3].children.push({key:t50.code,title:t50.code.concat('  ',t50.name),children:[]});
      })
})
})
//第七层：
 t7.map((t70)=>{
     ctree[0].children.map((c71,index1)=>{
             ctree[0].children[index1].children.map((c73,index3)=>{
                      ctree[0].children[index1].children[index3].children.map((c75,index5)=>{
                   if(t70.higher_code===c75.key)
                        ctree[0].children[index1].children[index3].children[index5].children.push({key:t70.code,title:t70.code.concat('  ',t70.name),children:[]});
      })
})
})
})
//第九层：
 t9.map((t90)=>{
     ctree[0].children.map((c91,index1)=>{
             ctree[0].children[index1].children.map((c93,index3)=>{
                      ctree[0].children[index1].children[index3].children.map((c95,index5)=>{
                              ctree[0].children[index1].children[index3].children[index5].children.map((c97,index7)=>{
                   if(t90.higher_code===c97.key)
                        ctree[0].children[index1].children[index3].children[index5].children[index7].children.push({key:t90.code,title:t90.code.concat('  ',t90.name),children:[]});
      })
})
})
})
})
//6层转换结束，应返回值
return ctree;
}

 //1连接数据库取数，2再通过内部函数迭代，3生成字串返回--------------------------------生成区域树--------------------------------------------
app.get('/basis_api/areatree',function(req,res){
 // function xx(){  //函数开始
       var sql='select * from base_area order by code asc';
       pool.getConnection(function(err,conn){
             if(err)  console.log('连接池错误。。。。。');
             else
              console.log('连接池成功。。。。');
         conn.query(sql,function(err,results){
       //返回数据，要用对象，且包含data或其他接口规范的数据
       //    var j={success:'ok',data:{success:true,data:results}};  
           //   console.log(j);
          //    res.send(j);
         //调用函数生成树
       
          var ctree=buildTree(results);

//console.log('CTREE-------'+JSON.stringify(ctree));
//res.send(JSON.stringify(ctree));
 //返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:true,data:ctree};  
              res.send(j);
          });
         conn.release();
    });
   
//   }//函数结束

 });   //----------------------------------------------------------------------------生成区域树---结束-----------------------------------------------------------------

 //1连接数据库取数，2再通过内部函数迭代，3生成字串返回--------------------------------生成物料分类树--------------------------------------------
 app.get('/basis_api/treedata/materialcategory',function(req,res){
  // function xx(){  //函数开始
        var sql='select * from material_category order by code asc';
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
        //    var j={success:'ok',data:{success:true,data:results}};  
            //   console.log(j);
           //    res.send(j);
          //调用函数生成树
        
           var ctree=buildTree(results);
 
 //console.log('CTREE-------'+JSON.stringify(ctree));
 //res.send(JSON.stringify(ctree));
  //返回数据，要用对象，且包含data或其他接口规范的数据
               var j={success:true,data:ctree};  
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });   //----------------------------------------------------------------------------生成区域树---结束-----------------------------------------------------------------
 
 
 //1连接数据库取数，2再通过内部函数迭代，3生成字串返回--------------------------------生成组织树--------------------------------------------
app.get('/basis_api/orgtree',function(req,res){
 // function xx(){  //函数开始
       var sql='select * from base_organization';
       pool.getConnection(function(err,conn){
             if(err)  console.log('连接池错误。。。。。');
             else
              console.log('连接池成功。。。。');
         conn.query(sql,function(err,results){
       //返回数据，要用对象，且包含data或其他接口规范的数据
        
 //调用函数生成树
          var ctree=buildTree(results);

 //返回数据，要用对象，且包含data或其他接口规范的数据
             var j={success:true,data:ctree};  
              res.send(j);
          });
         conn.release();
    });
   
//   }//函数结束

 });   //----------------------------------------------------------------------------生成组织树---结束-----------------------------------------------------------
 
//获取仓库列表--------------------------------------------------------------------基础档案：仓库列表--开始-----------------------------------------------------------------
app.get('/basis_api/warehousetable/xid/:x_id/:org_id',function(req,res){    //带参数为组织编号
  const x_id=req.params.x_id;
  const org_id=req.params.org_id;
  var sql='select * from v_warehouse where x_id=? ';
  var opt=[x_id];

  if(org_id!=0){
    sql=sql+' and org_id=? order by id';
    opt=[x_id,org_id];
  }else
    sql=sql+' order by id';

  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      res.send(j);
       });
   conn.release();
});
 });

//获取仓库列表--------------------------------------------------------------------基础档案：仓库列表--结束-----------------------------------------------------------------

//获取区域信息-----------------------------------------------获取区域信息-------开始-----------------------------------------------
//按传入的区域编号，显示本级和上级信息
app.get('/basis_api/area/:code',function(req,res){
    var sql='select * from v_area';
    var opt=[];
    
       sql=sql+'  where code=?';
       opt=[req.params.code];
   

    pool.getConnection(function(err,conn){
        if(err)
          console.log('区域数据取数失败!');
        else
          console.log('区域数据连接成功！');
        conn.query(sql,opt,function(err,results){
       var j={success:true,data:results[0]};
       console.log(j);
        res.send(j);
       });
      conn.release();
});
});
//获取区域信息-----------------------------------------------获取区域信息-----------结束-----------------------------------------------
 
//区域数据更新----------------------------------------------------------------------------更新区域信息-------开始----------
//app.use(bodyParser.urlencoded({extended:false}));
//app.use(bodyParser.json());

app.post('/basis_api/area/update',function(req,res){//---1
var etype=req.body.ttype;    
var tdata=req.body.tdata;
var x_id=req.body.x_id;
var operater_id=req.body.operater_id;

    console.log('JSON输出参数值：'+JSON.stringify(tdata));  //获取参数，注意前端调用request时，要用data:参数对象
  //  res.send({data:'成功更新数据'});
    var sql='call p_updatearea(?,?,?,?)';
    var opt=[x_id,operater_id,etype,JSON.stringify(tdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。


//先创建连接池，再通过连接执行语句
    pool.getConnection(function(err,conn){   //--2
        if(err)
          console.log('连接池错误');
        else
         console.log('连接数据库成功');
       
    conn.query(sql,opt,function(err,results){   //执行SQL--3
        if(err){
           console.log(err);
         res.end(JSON.stringify({success:false}));
       }
        else{//--4
        //从数据库返回结果，传前端state即时更新树    
        console.log('返回的数据：'+JSON.stringify(results));
        res.end(JSON.stringify({success:true,data:buildTreeById(results[0])}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
          
      
        }//--4
   });//--3
    conn.release(); 
  } );//连接池结束--2
   

  });//--1
//区域数据更新----------------------------------------------------------------------------更新区域信息-------结束----------

//--------------------------------------------------------通用树更新--------------------------------------------
app.post('/basis_api/fulltree/update',function(req,res){//---1
  // var etype=req.body.ttype;    
  // var tdata=req.body.tdata;
  // var x_id=req.body.x_id;
  // var operater_id=req.body.operater_id;
  const {ttype,tdata,x_id,operater_id,treeType}=req.body;
  
      console.log('JSON输出参数值：'+JSON.stringify(tdata));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
      var sql='call p_updatebasetree(?,?,?,?,?)';
      var opt=[x_id,operater_id,ttype,JSON.stringify(tdata),treeType];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。
      console.log('更新树的参数值：'+sql);
      console.log('更新树的参数值：'+JSON.stringify(opt));
  
  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //从数据库返回结果，传前端state即时更新树    
          console.log('返回的数据：'+JSON.stringify(results));
          res.end(JSON.stringify({success:true,data:buildTreeById(results[0])}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
     
  
    });//--1
  //区域数据更新----------------------------------------------------------------------------更新区域信息-------结束----------

  
//获取组织信息-----------------------------------------------获取组织信息-------开始-----------------------------------------------
//按传入的组织编号，显示本级和上级信息
app.get('/basis_api/organization/:code',function(req,res){
    var sql='select * from v_organization';
    var opt=[];
    
       sql=sql+'  where status=1 and  code=?';
       opt=[req.params.code];
   

    pool.getConnection(function(err,conn){
        if(err)
          console.log('组织数据取数失败!');
        else
          console.log('组织数据连接成功！');
        conn.query(sql,opt,function(err,results){
       var j={success:true,data:results[0]};
       console.log(j);
        res.send(j);
       });
      conn.release();
});
});
//获取区域信息-----------------------------------------------获取组织信息-----------结束-----------------------------------------------

//获取应用注册信息。当传入参数为0时，返回整个数据表---------------------------获取注册APP信息---开始-----------------------
app.get('/basis_api/app/register/:code',function(req,res){
    // var sql='select code,name,serverip,begin_date,status from v_app_register';
    var sql='select * from v_app_register';
    var opt=[req.params.code];
    // console.log(opt[0]);
    if(opt[0]!='0'){//opt返回的是一个组.如传为为0时，默认返回所有信息。
      sql=sql+' where code=?';
    }
    pool.getConnection(function(err,conn){
        if(err)
          res.send({success:false,error:'创建连接错误：'+err.message});
        conn.query(sql,opt,function(err,results){
            if(err)
                res.send({success:false,error:'查询数据库错误:'+err.message});
            var j={success:true,data:results};
         //   console.log(JSON.stringify(j));
            res.send(j);
        });
        conn.release();
    });
})
//获取应用注册信息。当传入参数为0时，返回整个数据表---------------------------获取注册APP信息---结束--------------
//更新应用注册，修改或更新------------------------------------------------------------------
app.post('/basis_api/app/register',function(req,res){//---1
  //var d2=req.body.paramm;
  var etype=req.body.etype;
  var tdata=req.body.tdata
  console.log('JSON输出：'+JSON.stringify(etype));  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据tdata:'+JSON.stringify(tdata));
//  res.send({data:'成功更新数据'});
  var sql='call p_saveappregister(?,?)';
  var opt=[etype,JSON.stringify(tdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:'error'})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:'ok'}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});



//获取接口注册信息。---------------------当传入0时，返回MDM接口；传入1时，返回非MDM接口----------------------------------------------------
app.get('/basis_api/app/interface/register/:code',function(req,res){
  var sql='select * from v_app_interface';
  var opt=[req.params.code];
  if(opt[0]==='0')
     sql=sql+' where code like "MDM%"';
  if(opt[0]==='1')
     sql=sql+' where code not like "MDM%"';
  if(opt[0]!='0'&&opt[0]!='1')
     sql=sql+' where code=?';
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         var j={success:true,data:results};
         res.send(j);
     });
     conn.release();
  });
});

//更新接口注册，修改或更新------------------保存接口注册信息--开始----------------------------------------------
app.post('/basis_api/app/interface/register',function(req,res){//---1
  //var d2=req.body.paramm;
  var etype=req.body.etype;
  var tdata=req.body.tdata
  console.log('JSON输出：'+JSON.stringify(etype));  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据tdata:'+JSON.stringify(tdata));
//  res.send({data:'成功更新数据'});
  var sql='call p_saveinterfaceregister(?,?)';
  var opt=[etype,JSON.stringify(tdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:'error'})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:'ok'}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//保存组织新增或更新------------------保存组织信息--开始----------------------------------------------
app.post('/basis_api/organization/save',function(req,res){//---1
  //var d2=req.body.paramm;
  var etype=req.body.etype; // 1新增 ，0修改
  var fdata=req.body.fdata;
  var x_id=req.body.x_id;
  var operater_id=req.body.operater_id;

  console.log('JSON输出：'+JSON.stringify(etype));  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据tdata:'+JSON.stringify(fdata));
  
//  res.send({data:'成功更新数据'});
  var sql='call p_saveorganization(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:buildTreeById(results[0])}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//保存仓库新增或更新------------------保存仓库信息--开始----------------------------------------------
app.post('/basis_api/warehouse/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const  etype=req.body.etype; // 1新增 ，0修改
  const  fdata=req.body.fdata
  const  x_id=req.body.x_id;
  const  operater_id=req.body.operater_id;

//  res.send({data:'成功更新数据'});
  var sql='call p_savewarehouse(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/roleuser/get/:role_id  ---------------------按角色获取已分配的用户-----2024-10-17--------------------------------
app.get('/basis_api/roleuser/get/:role_id',function(req,res){
  var sql='select * from v_roleuser where 1=1 ';
  var opt=[];
  if(req.params.role_id!=0){
      sql=sql+' and role_id=?'
      opt=[req.params.role_id]};

  console.log('用户角色连接SQL：'+sql);
  console.log('用户角色参数：'+JSON.stringify(opt));

  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         var j={success:true,data:results};
         res.send(j);
     });
     conn.release();
  });
});

///basis_api/roleuser/update-------------------------更新用户角色分配：新增或取消-------------------------
app.post('/basis_api/roleuser/update',function(req,res){

  const {x_id,operater_id,etype,role_id,user_ids}=req.body;   //user_id为0时代表全部
  
  var sql='call p_updateroleuser(?,?,?,?,?)';
  var opt=[x_id,operater_id,etype,role_id,JSON.stringify(user_ids)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('更新用户角色SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('更新用户角色OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4;
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/roleuser/unallocate/get/:role_id  ----------查询角色未分配用户列表-----------------------
app.get('/basis_api/roleuser/unallocate/get/:role_id',function(req,res){
  var {role_id}=req.params;
  var sql='select a.id,a.code,a.name,a.sex,b.name as org_name from base_person a join base_organization b on a.dep_id=b.id and a.isuser=1 and a.status=1 and a.id not in(select user_id from base_userrole where role_id=? )';
  var opt=[role_id];
  
  // if(role_id!=0){
  //   sql=sql+' where x_id=? and id=?';
  //   opt=[x_id,role_id];
  // }
console.log('角色列表SQL语句：'+sql);
console.log('角色列表OPT参数：'+JSON.stringify(opt));
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         else{
         var j={success:true,data:results};
         res.send(j);  
        }
     });
     conn.release();
  });
}); 
//basis_api/user/get----------------------------------获取用户信息-------------------------
app.post('/basis_api/user/get',function(req,res){

  const {x_id,user_id,org_ids}=req.body;   //user_id为0时代表全部
  
  var sql='call p_getuserinfo(?,?,?)';
  var opt=[x_id,user_id,JSON.stringify(org_ids)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


///basis_api/user/save
//保存用户新增或更新------------------保存用户信息--开始----------------------------------------------
app.post('/basis_api/user/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const {x_id,operater_id,etype,fdata}=req.body;

  var sql='call p_saveuserinfo(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL保存用户信息：'+JSON.stringify(sql));  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT保存用户信息:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回的数据，是在存储过程中保存后，的select语句
      //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功:'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/role/get/:x_id/:role_id
//获取角色信息，如code是undefined或999,则全部返回--------------------------------------------------------------------
app.get('/basis_api/role/get/:x_id/:role_id',function(req,res){
  var {x_id,role_id}=req.params;
  var sql='select * from  v_role order by id ';
  var opt=[];
  
  if(role_id!=0){
    sql=sql+' where x_id=? and id=?';
    opt=[x_id,role_id];
  }
console.log('角色列表SQL语句：'+sql);
console.log('角色列表OPT参数：'+JSON.stringify(opt));
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         else{
         var j={success:true,data:results};
         res.send(j);  
        }
     });
     conn.release();
  });
}); 

//保存角色新增或更新------------------保存角色信息--开始----------------------------------------------
app.post('/basis_api/role/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const {x_id,operater_id,etype,fdata}=req.body;
  var sql='call p_saverole(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];    
                //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('更新成功：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//`/basis_api/role/org/get/:org_id   获取角色对应的分配组织信息-----------------------
app.get('/basis_api/role/org/get/:org_id',function(req,res){
  var org_id=req.params.org_id;
  var sql='select * from  v_orgrole where status=1 ';
  var opt=[];
  
  //if(org_id!=undefined){
    sql=sql+' and  org_id=? order by id';
    opt=[org_id];
 // }
 
console.log('SQL语句：'+sql);
console.log('参数OPT:'+JSON.stringify(opt));
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         else{
         var j={success:true,data:results};
         
         res.send(j);  
        }
     });
     conn.release();
  });
}); 

//`/basis_api/role/user/:allocate_id   获取角色对应的--分配用户信息-----------------------
app.get('/basis_api/role/user/:allocate_id',function(req,res){
  var allocate_id=req.params.allocate_id;
  var sql='select * from  v_userrole where status=1 ';
  var opt=[];
  
  if(allocate_id!=undefined){
    sql=sql+' and allocate_id=? order by allocate_id';
    opt=[allocate_id];
  }
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         else{
         var j={success:true,data:results};
         res.send(j);  
        }
     });
     conn.release();
  });
}); 


///basis_api/role/org/allocated  ------------------------------查询角色已分配组织的ID---------------------
app.get('/basis_api/role/org/allocated/:role_id',function(req,res){
   var role_id=req.params.role_id;
  var sql='select b.id from  v_orgrole a join base_organization b on a.org_id=b.id ';
  sql=sql+' where a.item_type=3 and b.org_type in(1,2) and a.status=1 and a.item_id=? ';
  var opt=[role_id];
  
  //if(code!='999'){
  //  sql=sql+' where allocate_id=?';
  //  opt=[code];
 // }
 
 console.log('SQL语句：'+sql);
 console.log('OPT参数：'+JSON.stringify(opt));
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         else{
         var j={success:true,data:results};
         res.send(j);  
        }
     });
     conn.release();
  });
}); 

//保存角色分配组织信息------------------保存角色分配组织信息--开始----------------------------------------------
app.post('/basis_api/role/org/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const {x_id,operater_id,fdata,role_id}=req.body;

  var sql='call p_saveorgrole(?,?,?,?)';
  var opt=[x_id,operater_id,role_id,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL语句:'+sql);
  console.log('OTP参数:'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜:'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/role/org/user/allocated  ------------------------------查询角色已分配组织的用户的ID---------------------
app.get('/basis_api/role/org/user/allocated/:allocate_id',function(req,res){
  var allocate_id=req.params.allocate_id;
 //var sql='select code from  v_orgrole a join base_organization b on a.org_code=b.code 
 //where a.item_type=3 and b.org_type in(1,2) and a.item_code=? ';
 var sql='select user_id as id from v_userrole where status=1 and allocate_id=?'
 var opt=[allocate_id];
 
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));
 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

//保存角色+组织，分配用户组织信息------------------保存角色+组织,分配用户信息--开始----------------------------------------------
app.post('/basis_api/role/org/user/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const {x_id,operater_id,allocate_id,fdata}=req.body;
 
  var sql='call p_saveuserrole(?,?,?,?)';
  var opt=[x_id,operater_id,allocate_id,JSON.stringify(fdata)];  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜:'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//1连接数据库取数，2再通过内部函数迭代，3生成字串返回--------------------------------生成计量单位组树--------------------------------------------
app.get('/basis_api/unitgrouptree',function(req,res){
  // function xx(){  //函数开始
        var sql='select * from unitgroup';
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
         
  //调用函数生成树
          if(err){
            res.send({success:'error',data:'数据库取数异常。。。'});
            console.log('生成计量单位组树失败。');
          }else{
           var ctree=buildTree(results);
            
  //返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:true,data:ctree};  
              console.log('生成计量单位组成功：'+JSON.stringify(j));
               res.send(j);
           };
           });
          
          conn.release();
     });
    
 //   }//函数结束
 
  });   //----------------------------------------------------------------------------生成组织树---结束-----------------------------------------------------------
  

///basis_api/unit/get/:code  ---------------------------------获取计量单位表----------------------------------
app.get('/basis_api/unit/get/:code',function(req,res){
  var code=req.params.code;
  var sql='select * from v_unit '
  var opt=[];
 
  if(code!='999'){   //999默认为全部
   sql=sql+' where code=?';
   opt=[code];
 }

console.log(sql);
console.log(opt);
 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 


///basis_api/unit/save------------------------------------保存计量单位信息--------------------------------------
app.post('/basis_api/unit/save',function(req,res){//---1
  //var d2=req.body.paramm;
  var etype=req.body.etype; 
  var fdata=req.body.fdata
  console.log('JSON输出etype：'+etype);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据fdata:'+JSON.stringify(fdata));
  
//  res.send({data:'成功更新数据'});
  var sql='call p_saveunit(?,?)';
  var opt=[etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:'error'})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:'ok'}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/materialcategory/get/:id----------------------------------获取存货分类明细信息-----------------------------------
app.get('/basis_api/materialcategory/get/:id',function(req,res){
  var id=req.params.id;
  var sql='select * from v_materialcategory '
  var opt=[];
 
  if(id!=0){   //0默认为全部
   sql=sql+' where id=? order by id';
   opt=[id];
 }

console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 


///basis_api/materialcategory/save---------------------------保存物料分类信息--------------------------------
app.post('/basis_api/materialcategory/save',function(req,res){//---1
 const {x_id,operater_id,etype,fdata}=req.body;

  var sql='call p_savematerialcategory(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL语句：'+sql);   
  console.log('OPT参数:'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
      res.end(JSON.stringify({success:true,data:buildTreeById(results[0])}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜:'+JSON.stringify({success:true,data:buildTreeById(results[0])}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/material/xid/get/  ----------------------根据物料分类和编码，取物料档案 -----------------
app.post('/basis_api/material/xid/get',function(req,res){

  const {x_id,cate_id,id,mtype,fdata}=req.body;
  
  var sql='call p_getmaterialinfo(?,?,?,?,?)';
  var opt=[x_id,id,mtype,JSON.stringify(cate_id),JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/material/xid/get/craft/  ----------------------根据物料分类和编码，取物料档案 -----------------
app.post('/basis_api/material/xid/get/craft',function(req,res){

  const {x_id,cate_id,id,mtype,fdata}=req.body;
  
  var sql='call p_getmaterialcraft(?,?,?,?,?)';
  var opt=[x_id,id,mtype,JSON.stringify(cate_id),JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/document/xid/get/  ----------------------根据分类，取下属档案 -----通用2025-03-16------------
app.post('/basis_api/document/xid/get',function(req,res){

  const {x_id,cate_id,id,source}=req.body;
  
  var sql='call p_getdocumentinfo(?,?,?,?)';
  var opt=[x_id,id,source,JSON.stringify(cate_id)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/materialgroup/xid/get----------------------------获取物料组明细--------------------
app.post('/basis_api/materialgroup/xid/get',function(req,res){

  const {x_id,tdata}=req.body;
  
  var sql='call p_getmaterialgroup(?,?)';
  var opt=[x_id,JSON.stringify(tdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});
 
//basis_api/common/stock/out/xid  --------------------库存模块出库业务  集中处理2025-04-22----------------------------
app.post('/basis_api/common/stock/out/xid',function(req,res){

  const {x_id,operater_id,etype,source,tdata}=req.body;
  
  var sql='call  p_stock_out(?,?,?,?,?)';
  var opt=[x_id,operater_id,etype,source,JSON.stringify(tdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err){
            console.log('连接池错误');
            res.s({success:false,error:err});
        }
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
          res.send({success:false,error:err.message}); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.send({success:true,data:results});
        console.log('库存出库返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//basis_api/common/stock/in/xid  --------------------库存模块入库业务  集中处理2025-04-24----------------------------
app.post('/basis_api/common/stock/in/xid',function(req,res){

  const {x_id,operater_id,etype,source,tdata}=req.body;
  
  var sql='call  p_stock_in(?,?,?,?,?)';
  var opt=[x_id,operater_id,etype,source,JSON.stringify(tdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err){
            console.log('连接池错误');
            res.s({success:false,error:err});
        }
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
          res.send({success:false,error:err.message}); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.send({success:true,data:results});
        console.log('库存出库返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//库存模块数据集中查询---------------------------------2025-05-22----------------------------------------------
///basis_api/common/stock/get/info
app.post('/basis_api/common/stock/get/info',function(req,res){

  const {x_id,cate_id,id,source,fdata}=req.body;
  
  var sql='call p_stock_getinfo(?,?,?,?,?)';
  var opt=[source,x_id,id,JSON.stringify(cate_id),JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回库存数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//生产模块数据集中查询---------------------------------2025-05-31----------------------------------------------
///basis_api/common/produce/get/info
app.post('/basis_api/common/produce/get/info',function(req,res){

  const {x_id,cate_id,id,source,fdata}=req.body;
  
  var sql='call p_produce_getinfo(?,?,?)';
  var opt=[x_id,source,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
      console.log('返回生产数据：'+JSON.stringify({success:true,data:results}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//销售模块数据集中查询---------------------------------2025-05-30---------------------------------------------
app.post('/basis_api/common/sale/get/info',function(req,res){

  const {x_id,cate_id,id,source,fdata}=req.body;
  
  var sql='call p_sale_getinfo(?,?,?,?,?)';
  var opt=[source,x_id,id,JSON.stringify(cate_id),JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回销售数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


///basis_api/common/purchase/get/info--------------------------采购信息查询--2025-05-24------------------------
app.post('/basis_api/common/purchase/get/info',function(req,res){

  const {x_id,source,fdata}=req.body;
  
  var sql='call p_purchase_getinfo(?,?,?)';
  var opt=[x_id,source,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回采购数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/common/tableinfo/xid/get/  ----------------------根据多级分类和编码，取表格数据 -通用-2024-12-31-加油--------------
app.post('/basis_api/common/tableinfo/xid/get',function(req,res){

  const {x_id,cate_id,id,source,fdata}=req.body;
  
  var sql='call p_getcommontableinfo(?,?,?,?,?)';
  var opt=[source,x_id,id,JSON.stringify(cate_id),JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/common/tableinfo/coditoion/get/  ----------------------根据多条件进行取数，取表格数据 -通用-2025-01-06---------------
app.post('/basis_api/common/tableinfo/condition/get',function(req,res){

  const {x_id,source,tdata}=req.body;
  
  var sql='call p_getcommontableinfobycondition(?,?,?)';
  var opt=[x_id,source,JSON.stringify(tdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results}));
        console.log('返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///获取图片或文件--测试---/mes_basis/file/get/:filename--------------------------------------------
// 返回前端
  app.get('/basis_api/file/get',function(req,res){//---1
  // 参数为：文件路径
  const {filename}=req.query;
  var filePath=filename;
  console.log("文件名称"+filename); 
  if(filename.toLocaleLowerCase().indexOf(".pdf")>0){
    // res.status(500).send('Error loading PDF.');
    res.contentType('application/pdf');
    var stream = fs.createReadStream( filePath );
    var responseData = [];//存储文件流
   if (stream) {//判断状态
      stream.on( 'data', function( chunk ) {
        responseData.push( chunk );
      });
      stream.on( 'end', function() {
         var finalData = Buffer.concat( responseData );
         res.write( finalData );
         res.end();
      });
  }
    // fs.readFile(filePath, (err, data) => {
    //   if (err) {
    //     res.status(500).send('Error loading PDF.');
    //   } else {
    //     res.contentType('application/pdf');
    //     res.send(data);
    //     res.end();
    //   }
    // });     
  }else{  
  // 给客户端返回一个文件流 type类型
  res.set( 'content-type', {"png": "image/png","jpg": "image/jpeg"} );//设置返回类型
  var stream = fs.createReadStream( filePath );
  var responseData = [];//存储文件流
  if (stream) {//判断状态
      stream.on( 'data', function( chunk ) {
        responseData.push( chunk );
      });
      stream.on( 'end', function() {
         var finalData = Buffer.concat( responseData );
         res.write( finalData );
         res.end();
      });
  }
};
});


///获取图片或文件- --/mes_basis/file/get/:filename------------2025-06-16按默认物料编码，返回图片-----------------
// 返回前端
  app.get('/basis_api/file/get2',function(req,res){//---1
  // 参数为：文件路径
  const {filename}=req.query;
  // var filePath='c:\\additions\\1\\material\\'+filename+'.jpg';
  console.log("文件名称"+filename); 
  // if(filename.toLocaleLowerCase().indexOf(".pdf")>0){
  //   // res.status(500).send('Error loading PDF.');
  //   res.contentType('application/pdf');
  //   var stream = fs.createReadStream( filePath );
  //   var responseData = [];//存储文件流
  //  if (stream) {//判断状态
  //     stream.on( 'data', function( chunk ) {
  //       responseData.push( chunk );
  //     });
  //     stream.on( 'end', function() {
  //        var finalData = Buffer.concat( responseData );
  //        res.write( finalData );
  //        res.end();
  //     });
  // }
  //   // fs.readFile(filePath, (err, data) => {
  //   //   if (err) {
  //   //     res.status(500).send('Error loading PDF.');
  //   //   } else {
  //   //     res.contentType('application/pdf');
  //   //     res.send(data);
  //   //     res.end();
  //   //   }
  //   // });     
  // }else
  // {  
  // 给客户端返回一个文件流 type类型
  res.set( 'content-type', {"png": "image/png","jpg": "image/jpeg"} );//设置返回类型
   var filePath='c:\\images\\'+filename+'.JPG';
   //判断文件是否存在，否则默认为0.jpg
    try {
       fs.accessSync(filePath, fs.constants.F_OK);
        console.log('文件名存在。');
   } catch (err) {
       console.log('文件名不存在。000000');
       filePath='c:\\images\\0.JPG';
    }

    console.log('文件名输出为：'+filePath);
  var stream = fs.createReadStream( filePath );
  var responseData = [];//存储文件流
  if (stream) {//判断状态
      stream.on( 'data', function( chunk ) {
        responseData.push( chunk );
      });
      stream.on( 'end', function() {
         var finalData = Buffer.concat( responseData );
         res.write( finalData );
         res.end();
      });
  // }
};
});


//  /basis_api/material/xid/save---------------------------------保存物料信息--------------------------------
app.post('/basis_api/material/xid/save',function(req,res){//---1
  const {x_id,operater_id,etype,fdata}=req.body;

  var sql='call p_savematerial(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL语句：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT参数:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
           console.log(err);
           res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
          res.end(JSON.stringify({success:true,data:'返回数据成功'}));
          // console.log('数据库更新成功，恭喜：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//  //basis_api/material/image/del---------------------------------删除本地多余的图片文件-------------------------------
app.post('/basis_api/material/image/del',function(req,res){//---1
  // const {x_id,operater_id,etype,fdata}=req.body;

  var sql='select code from material';
  var opt=[];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL语句：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT参数:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
           console.log(err);
           res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
          // res.end(JSON.stringify({success:true,data:'返回数据成功'}));
          console.log('数据库更新成功，恭喜：'+JSON.stringify({success:true,data:results }));
          //取出文件名后 ，两个数组对比，删除多余的文件
       
      var imgfiles=[];

     try {
        const files = fs.readdirSync('c:\\images');
         console.log('Directory contents:', files);
         imgfiles=files;
      } catch (err) {
         console.error('Error reading directory:', err);
      };

       console.log('目录中存在的文件名：'+JSON.stringify(imgfiles));

       imgfiles=imgfiles.map(item=>item.substring(0,item.length-4));
       var resu=results.map(item=>item.code);
       console.log('res中的code：'+resu[0]);
        //求差集
       var diff=imgfiles.filter(item=>res.indexOf(item)==-1);
       console.log('多余的文件名:'+JSON.stringify(diff));

       //删除文件
       diff.map(item=>{
          try {
           fs.unlinkSync('c:\\images\\'+item+'.JPG');
             console.log('删除：'+item+'.JPG');
      } catch (err) {
          console.error('Error deleting file:', err);
      };

       });
       res.end({success:true});
          
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//  /basis_api/material/group/xid/save---------------------------------保存物料组     信息--------------------------------
app.post('/basis_api/material/group/xid/save',function(req,res){//---1
  const {x_id,operater_id,etype,fdata}=req.body;

  var sql='call p_savematerialgroup(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL语句：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT参数:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
           console.log(err);
           res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
          res.end(JSON.stringify({success:true,data:results[0]}));
          console.log('数据库更新成功，恭喜：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//`/basis_api/material/allocate/:code   获取角色对应的分配组织信息-----------------------
app.get('/basis_api/allocate/:item_type/:item_code',function(req,res){
  var code=req.params.role_code;
  var sql='select * from  v_allocate where status=1 and item_type=3 ';
  var opt=[];
  
  if(code!='999'){
    sql=sql+' and  item_code=?';
    opt=[code];
  }
 
console.log(sql);
console.log(opt);
  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
         else{
         var j={success:true,data:results};
         res.send(j);  
        }
     });
     conn.release();
  });
}); 

///basis_api/allocate/org/:x_id/:item_type/:item_id  ----------通用？,按类型和组织----查询项目已分配组织的ID---------------------
app.get('/basis_api/allocate/org/:x_id/:item_type/:item_id',function(req,res){
 const {x_id,item_type,item_id}=req.params;
 var sql='select org_id as id from  v_allocate_global ';
 sql=sql+' where  x_id=? and   item_type=?  and item_id=?  order by id';
 var opt=[x_id,item_type,item_id];
 

console.log('SQL语句已分配组织ID:'+sql);
console.log('opt语句已分配组织ID:'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        console.log('查询结果-已分配组织：'+JSON.stringify(j));
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/allocate/org/save----------------------通用：保存项目+组织的分配结果----------------------------------
app.post('/basis_api/allocate/org/save',function(req,res){//---1
 
  const {x_id,operater_id,item_type,item_id,fdata}=req.body;
 
  var sql='call p_saveorgallocate(?,?,?,?,?)';
  var opt=[x_id,operater_id,item_type,item_id,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
    //先创建连接池，再通过连接执行语句
  console.log('分配组织SQL语句:'+sql);
  console.log('分配组织OPT参数:'+JSON.stringify(opt));
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/userdefine/get/:x_id/:source/:code ----------------获取用户自定项列表------------------------
app.get('/basis_api/userdefine/get/:x_id/:source/:code',function(req,res){
  var source=req.params.source;
  var code=req.params.code;
  var x_id=req.params.x_id;

 var sql='select * from  v_userdefine where x_id=? ';
 var opt=[x_id];

 if(source!='999')
    if(code==='999'){
      sql=sql+' and source_type=?  ';
      opt=[x_id,source];
    }else{
      sql=sql+' and source_type=? and code=? ';
      opt=[x_id,source,code];
    }
 
  
console.log(sql);
console.log(JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/userdefine/save-------------------------保存用户自定义项----------------------------------
app.post('/basis_api/userdefine/save',function(req,res){//---1
   const {x_id,operater_id,etype,fdata}=req.body;
   var sql='call p_saveuserdefine(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
  
  console.log('SQL保存自定义项：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT参数:'+JSON.stringify(opt));

  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/userdefine/doc/get/:source/:code --------------------获取用户自定义档案---------------------
app.get('/basis_api/userdefine/doc/get/:source/:code',function(req,res){
  var source=req.params.source;
  var code=req.params.code;
 var sql='select * from  v_userdefine_doc where 1=1 ';
 var opt=[];

 if(source!='999')
    if(code==='999'){
      sql=sql+' and userdefine_id=?  ';
      opt=[source];
    }else{
      sql=sql+' and userdefine_id=? and code=? ';
      opt=[source,code];
    }
 
  
console.log(sql);
console.log(JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/userdefine/doc/save-----------------------保存新添加的自定义档案值----------------------------
app.post('/basis_api/userdefine/doc/save',function(req,res){//---1
  const fdata=req.body.fdata
  const operater_id=req.body.operater_id;
  var sql='call p_saveuserdefine_doc(?,?)';
  var opt=[operater_id,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
  
  console.log('添加自定义项SQL:'+sql);
  console.log('添加自定义项OPT:'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/userdefine/doc/update --------------------批量更新自定义档案值，表格，不插入---------------------------
app.post('/basis_api/userdefine/doc/update',function(req,res){//---1
  const fdata=req.body.fdata;
  const operater_id=req.body.operater_id;
 
  var sql='call p_updateuserdefine_doc(?,?)';
  var opt=[operater_id,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL保存自定义档案:'+sql);
  console.log('opt保存自定义档案:'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/material/userdefine/xid/get/:etype/:item_code   -------------------编辑物料档案时，调用自定义项--------------------------
app.get('/basis_api/material/userdefine/xid/get/:x_id/:source_type/:item_id',function(req,res){
  
  const {x_id,source_type,item_id}=req.params;
 var sql='call p_getuserdefine(?,?,?)';  //注意：此处通过存储过程返回结果
 var opt=[x_id,source_type,item_id];

 console.log('SQL语句：'+sql);
 console.log('OPT参数：'+JSON.stringify(opt));  

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/material/userdefine/save---------------物料档案：保存自定义项---------------------------
app.post('/basis_api/material/userdefine/save',function(req,res){//---1
   const {x_id,operater_id,item_id,fdata}=req.body;
   var sql='call p_savematerial_userdefine(?,?,?,?)';
   var opt=[x_id,operater_id,item_id,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
 
  console.log('SQL语句：'+sql);
  console.log('OPT参数：'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

//1连接数据库取数，2再通过内部函数迭代，3生成字串返回--------------------------------生成客商分类树--------------------------------------------
app.get('/basis_api/treedata/business/category',function(req,res){
  // function xx(){  //函数开始
        var sql='select * from business_category order by code asc';
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
        //    var j={success:'ok',data:{success:true,data:results}};  
            //   console.log(j);
           //    res.send(j);
          //调用函数生成树
        
           var ctree=buildTree(results);
 
 //console.log('CTREE-------'+JSON.stringify(ctree));
 //res.send(JSON.stringify(ctree));
  //返回数据，要用对象，且包含data或其他接口规范的数据
               var j={success:true,data:ctree};  
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });   //----------------------------------------------------------------------------生成区域树---结束-----------------------------------------------------------------
 
///basis_api/business/category/get/----------------------------------获取客商分类明细信息-----------------------------------
app.get('/basis_api/business/category/get/:code',function(req,res){
  var code=req.params.code;
  var sql='select * from v_businesscategory '
  var opt=[];
 
  if(code!='999'){   //999默认为全部
   sql=sql+' where code=?';
   opt=[code];
 }

console.log(sql);
console.log(opt);
 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/business/category/save---------------------------保存物料分类信息--------------------------------
app.post('/basis_api/business/category/save',function(req,res){//---1
  const {x_id,operater_id,etype,fdata}=req.body;

  var sql='call p_savebusinesscategory(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。
  
  console.log('SQL保存客商分类：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT保存客商分类:'+JSON.stringify(opt));
  
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
      const x=buildTreeById(results[0]);//建立树  
      res.end(JSON.stringify({success:true,data:x}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜'+JSON.stringify({success:true,data:x}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

// basis_api/business/xid/get-----------------------------根据客商分类和编码参，数获取客商档案-------
app.post('/basis_api/business/xid/get',function(req,res){

  const {x_id,cate_id,id}=req.body;
  
  var sql='call p_getbusinessinfo(?,?,?)';
  var opt=[x_id,id,JSON.stringify(cate_id)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results[0]}));
        console.log('获取客商信息返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

// basis_api/business/xid/org/get-----------------------------根据客商分类和编码参，数获取客户或供应商档案----注意区分客商档案---
//注意比客商列表，多org_id参数，返回客户或供应商
app.post('/basis_api/business/xid/org/get',function(req,res){

  const {x_id,org_id,cate_id,id}=req.body;
  
  var sql='call p_getbusinessinfo2(?,?,?,?)';
  var opt=[x_id,org_id,id,JSON.stringify(cate_id)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
    //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型----是否可切换为send+对象返回？            
      res.end(JSON.stringify({success:true,data:results[0]}));
        console.log('获取客商信息返回数据：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});



//---------------保存客商基础档案信息---------------------------------
app.post('/basis_api/business/xid/save',function(req,res){//---1
  const {x_id,operater_id,etype,fdata}=req.body;

  var sql='call p_savebusiness(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL语句：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT参数:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
           console.log(err);
           res.end(JSON.stringify({success:false,error:err.message})); //
     }
      else{//--4
          res.end(JSON.stringify({success:true,data:results[0]}));
          console.log('供应商更新成功，恭喜：'+JSON.stringify({success:true,data:results[0]}));
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//basis_api/business/define/get/:org_id/:item_id   -----------------------获取客商的已分配信息------------------
app.get('/basis_api/business/define/get/:org_id/:item_id',function(req,res){
  var item_id=req.params.item_id;
  var org_id=req.params.org_id;
  var sql='select * from v_business_define where org_id=? and item_id=? order by id  '
  var opt=[org_id,item_id];

console.log('SQL语句客商管理：'+sql);
console.log('OPT参数客商管理：'+JSON.stringify(opt));
 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/business/define/save --------------------保存客商定义信息：目前仅分类-----------------------------
app.post('/basis_api/business/define/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const  fdata=req.body.fdata;
  const  operater_id=req.body.operater_id;
 // console.log('JSON输出etype：'+etype);  //获取参数，注意前端调用request时，要用data:参数对象
 
  
//  res.send({data:'成功更新数据'});
  var sql='call p_savebusinessdefine(?,?)';
  var opt=[operater_id,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('SQL保存客商管理:'+sql);
  console.log('OPT保存客商管理:'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

///basis_api/business/doc/get/:cate_code/:code/:dtype  ----------------------获取供应商、客户档案-------------------
//dtype:1供应商，2客户
app.get('/basis_api/business/doc/get/:cate_code/:code/:dtype',function(req,res){
  var cate_code=req.params.cate_code;
  var code=req.params.code;
  var dtype=req.params.dtype;
  var sql='';
  if(dtype==='1')  //1为供应商，2为客户
    sql='select * from v_business_doc where  isvendor=1';
  else
    sql='select * from v_business_doc where  iscustomer=1';
  var opt=[];

 //以下传入code:999时，即为全部客、商信息；
  if(cate_code!='999'&&code!='999'){   //999默认为全部
      sql=sql+' and category_code like concat(?,"%") and code=?';
      opt=[cate_code,code];
 }else if(cate_code==='999'&&code!='999'){
      sql=sql+'   and code=?';
      opt=[code];
 }else if(cate_code!='999'&&code==='999'){
      sql=sql+'   and category_code  like concat(?,"%")';
      opt=[cate_code];
}

console.log('dtype:'+dtype);
console.log(sql);
console.log(opt);
 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/iotype/tree/get/:x_id--------------------------------获取收发类型树-----------------------------------------
app.get('/basis_api/iotype/tree/get/:x_id',function(req,res){
  // function xx(){  //函数开始
        const x_id=req.params.x_id;
        var sql='select * from base_iotype where x_id=? order by id ';
        var opt=[x_id];
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,opt,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
        //    var j={success:'ok',data:{success:true,data:results}};  
            //   console.log(j);
           //    res.send(j);
          //调用函数生成树
        
           var ctree=buildTreeById(results);
 
 //console.log('CTREE-------'+JSON.stringify(ctree));
 //res.send(JSON.stringify(ctree));
  //返回数据，要用对象，且包含data或其他接口规范的数据
               var j={success:true,data:ctree};  
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  

  ///basis_api/iotype/get/:id ---------------------------获取收发类别详细信息--------------------------
  app.get('/basis_api/iotype/get/:id',function(req,res){
    var sql='select * from v_iotype ';
    var opt=[];
    
       sql=sql+'  where id=?';
       opt=[req.params.id];
   pool.getConnection(function(err,conn){
        if(err)
          console.log('区域数据取数失败!');
        else
          console.log('区域数据连接成功！');
        conn.query(sql,opt,function(err,results){
       var j={success:true,data:results[0]};
       console.log(j);
        res.send(j);
       });
      conn.release();
});
});

//basis_api/iotype/update      ------------------------------------更新收发类别保存信息-------------------------
app.post('/basis_api/iotype/update',function(req,res){//---1
  const etype=req.body.etype;    
  const fdata=req.body.fdata;
  const x_id=req.body.x_id;
  const operater_id=req.body.operater_id;

  var sql='call p_updateiotype(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。
  
  console.log('SQL输出参数值：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('OPT值：'+JSON.stringify(opt));
  //  res.send({data:'成功更新数据'});
  
  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true,data:buildTreeById(results[0])}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('收发类型更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
     
  
    });//--1

///basis_api/ordertype/tree/get--------------------------------获取订单类型树-----------------------------------------
app.get('/basis_api/ordertype/tree/get',function(req,res){
  // function xx(){  //函数开始
        var sql='select * from base_ordertype order by code asc';
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
        //    var j={success:'ok',data:{success:true,data:results}};  
            //   console.log(j);
           //    res.send(j);
          //调用函数生成树
        
           var ctree=buildTreeById(results);
 
 //console.log('CTREE-------'+JSON.stringify(ctree));
 //res.send(JSON.stringify(ctree));
  //返回数据，要用对象，且包含data或其他接口规范的数据
               var j={success:true,data:ctree};  
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  

  ///basis_api/ordertype/get/:id ---------------------------获取订单类别详细信息--------------------------
  app.get('/basis_api/ordertype/get/:id',function(req,res){
    var sql='select * from v_ordertype where id=?';
    var opt=[req.params.id];
    pool.getConnection(function(err,conn){
        if(err)
          console.log('订单类别数据取数失败!');
        else
          console.log('订单类别数据连接成功！');
        conn.query(sql,opt,function(err,results){
       var j={success:true,data:results[0]};
       console.log(JSON.stringify(j));
        res.send(j);
       });
      conn.release();
});
});

//basis_api/ordertype/update      ------------------------------------更新收发类别保存信息-------------------------
app.post('/basis_api/ordertype/update',function(req,res){//---1
  const etype=req.body.etype;    
  const fdata=req.body.fdata;
  const x_id=req.body.x_id;
  const operater_id=req.body.operater_id;

      var sql='call p_updateordertype(?,?,?,?)';
      var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。
  
      console.log('SQL输出参数值：'+sql);
      console.log('OPT输出参数值：'+JSON.stringify(opt));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true,data:buildTreeById(results[0])}));
          //返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('数据库更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
   });//--1

////basis_api/business/state/update ------------------------保存客户合作状态-----------------------
app.post('/basis_api/business/state/update',function(req,res){//---1
  var item_id=req.body.item_id;    
  var state=req.body.state;
    //  console.log('JSON输出参数值：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
      //var sql='update business_document set state=? where code=?';
      var sql='call p_updatebusinessstate(?,?)';
      var opt=[item_id,state];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。

  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('数据库更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
   });//--1

   //保存X组织注册信息  /basis_api/organization/register--------------------------------------------------------
   app.post('/basis_api/xorganization/register',function(req,res){//---1
    var operater_id=req.body.operater_id;    
    var fdata=req.body.fdata;
      //  console.log('JSON输出参数值：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
      //  res.send({data:'成功更新数据'});
        var sql='call p_savex_organization(?,?)';
        var opt=[operater_id,JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。
  
    //先创建连接池，再通过连接执行语句
        pool.getConnection(function(err,conn){   //--2
            if(err)
              console.log('连接池错误');
            else
             console.log('连接数据库成功');
           
        conn.query(sql,opt,function(err,results){   //执行SQL--3
            if(err){
               console.log(err);
             res.end(JSON.stringify({success:false}));
           }
            else{//--4
            //本程序未更新树节点，以后可再优化     
            res.end(JSON.stringify({success:true}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
              console.log('数据库更新成功，恭喜');
          
            }//--4
       });//--3
        conn.release(); 
      } );//连接池结束--2
     });//--1
  
///basis_api/xorganiation/get/list  -----------------获取X组织的列表----------------------------------
app.get('/basis_api/xorganiation/get/list',function(req,res){
  var sql='select * from x_organization order by id';
  var opt=[];
  
  pool.getConnection(function(err,conn){
      if(err)
        console.log('订单类别数据取数失败!');
      else
        console.log('订单类别数据连接成功！');
      conn.query(sql,opt,function(err,results){
        if(err){
          console.log('X组织取数出错：'+JSON.stringify(err))
        }
     var j={success:true,data:results};
     console.log(j);
      res.send(j);
     });
    conn.release();
});
});


///basis_api/sysoptions/save  -------------------------保存X系统选项设置----------------
app.post('/basis_api/sysoptions/save',function(req,res){//---1
  var x_id=req.body.x_id;    
  var operater_id=req.body.operater_id;    
  var fdata=req.body.fdata;
    //  console.log('JSON输出参数值：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
      var sql='call p_savesysoptions(?,?,?)';
      var opt=[x_id,operater_id,JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。

  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('数据库更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
   });//--1

///basis_api/sysoptions/get/:x_id  ----------------------------获取X选项信息--------------------
app.get('/basis_api/sysoptions/get/:x_id',function(req,res){
  var sql='select * from sysoptions where x_id=? order by id';
  const x_id=req.params.x_id;
  var opt=[x_id];
  
  pool.getConnection(function(err,conn){
      if(err)
        console.log('订单类别数据取数失败!');
      else
        console.log('订单类别数据连接成功！');
      conn.query(sql,opt,function(err,results){
        if(err){
          console.log('X组织取数出错：'+JSON.stringify(err))
        }
     var j={success:true,data:results};
     console.log(j);
      res.send(j);
     });
    conn.release();
});
});


 //1连接数据库取数，2再通过内部函数迭代，3生成字串返回-------- ------------------------生成区域树X组织--------------------------------------------
 app.get('/basis_api/areatree/xid/:x_id',function(req,res){
  // function xx(){  //函数开始
       const x_id=req.params.x_id;
        var sql='select * from base_area where x_id=? and status=1 order by code asc';
        var opt=[x_id];
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,opt,function(err,results){
          if(err)
            console.log('生成区域树错误:'+JSON.stringify(err));
          else {
           var ctree=buildTreeById(results);
               var keys=results.map((item2)=>item2.id);
               var j={success:true,data:{ctree,keys}};  
            console.log('生成区域树数据：'+JSON.stringify(j));
               res.send(j);
           }});
          conn.release();
     });
 
  });   //----------------------------------------------------------------------------生成区域树---结束-----------------------------------------------------------------
 
  //连接数据库取渠道类别树，并生成树-------------------------------------生成渠道树X组织-------------------------------
  app.get('/basis_api/fulltree/xid/:x_id/:treeType',function(req,res){
    const {x_id,treeType}=req.params;
    const sql='select * from '+treeType+' where x_id=? and status=1 order by code asc';
    var opt=[x_id];
    pool.getConnection(function(err,conn){
      if(err)
        console.log('渠道类别连接错误，请检查。');
      else
        console.log('渠道类别连接成功。');
      conn.query(sql,opt,function(err,results){
         if(err)
            console.log('获取渠道类别错误！');
          else{
            var keys=results.map((item)=>item.id);
            var ctree=buildTreeById(results);
            var j={success:true,data:{ctree,keys}};  
            console.log('生成渠道类别树数据：'+JSON.stringify(j));
            res.send(j);
          }
      });
      conn.release();
    });
  });

//创建树形结构数据的迭代函数，此处为接收“区域”数据，并生成符合TREE字符串格式返回------按ID返回树结构数据------------------
function buildTreeById(rets){
  //最大5层，先分拆为5个数据集，再逐个生成
      var t0=[];
      rets.map((r)=>{
                 if(r.layer===0&&r.status!=3)
                     t0.push(r);
                    return;
            });

       var t1=[];
      rets.map((r)=>{
                 if(r.layer===1&&r.status!=3)
                     t1.push(r);
                    return;
            });
var t2=[];
      rets.map((r)=>{
                 if(r.layer===2&&r.status!=3)
                     t2.push(r);
                    return;
            });
var t3=[];
      rets.map((r)=>{
                 if(r.layer===3&&r.status!=3)
                     t3.push(r);
                    return;
            });
var t4=[];
      rets.map((r)=>{
                 if(r.layer===4&&r.status!=3)
                     t4.push(r);
                    return;
            });
var t5=[];
      rets.map((r)=>{
                 if(r.layer===5&&r.status!=3)
                     t5.push(r);
                    return;
            });
//逐个生成数组对象
var ctree=[];
ctree[0]={key:t0[0].id,title:t0[0].code.concat('  ',t0[0].name),children:[]};
//第一层
t1.map((t)=>{
   ctree[0].children.push({key:t.id,title:t.code.concat('  ',t.name),children:[]});
});
//第二层：需要先定位，再插入
t2.map((t20)=>{
   ctree[0].children.map((c2,index)=>{
       if(t20.higher_id===c2.key)
                ctree[0].children[index].children.push({key:t20.id,title:t20.code.concat('  ',t20.name),children:[]});
    })
})
//第三层：
t3.map((t30)=>{
   ctree[0].children.map((c31,index1)=>{
           ctree[0].children[index1].children.map((c32,index2)=>{
                 if(t30.higher_id===c32.key)
                      ctree[0].children[index1].children[index2].children.push({key:t30.id,title:t30.code.concat('  ',t30.name),children:[]});
    })
})
})
//第四层：
t4.map((t40)=>{
   ctree[0].children.map((c41,index1)=>{
           ctree[0].children[index1].children.map((c42,index2)=>{
                    ctree[0].children[index1].children[index2].children.map((c43,index3)=>{
                 if(t40.higher_id===c43.key)
                      ctree[0].children[index1].children[index2].children[index3].children.push({key:t40.id,title:t40.code.concat('  ',t40.name),children:[]});
    })
})
})
})
//第五层：
t5.map((t50)=>{
   ctree[0].children.map((c51,index1)=>{
           ctree[0].children[index1].children.map((c52,index2)=>{
                    ctree[0].children[index1].children[index3].children.map((c53,index3)=>{
                            ctree[0].children[index1].children[index2].children[index3].children.map((c54,index4)=>{
                 if(t50.higher_id===c54.key)
                      ctree[0].children[index1].children[index2].children[index3].children[index4].children.push({key:t50.id,title:t50.code.concat('  ',t50.name),children:[]});
    })
})
})
})
})
//5层转换结束，应返回值
return ctree;
}

////按传入的区域ID，显示本级和上级信息  --------------------------注意：此处是新改造，按ID。20240116---------------------
app.get('/basis_api/area/get/id/:id',function(req,res){
  var sql='select * from v_area where id=? and status=1';
  var opt=[req.params.id];
  console.log("SQL:"+sql);
  console.log("OPT:"+opt.length);
   pool.getConnection(function(err,conn){
      if(err)
        console.log('区域数据取数失败!');
      else
        console.log('区域数据连接成功！');
      conn.query(sql,opt,function(err,results){
     
     var j={success:true,data:results[0]};
     console.log(j);
      res.send(j);
     });
    conn.release();
});
});

////按传入的树类型+ID，显示本级和上级信息  -------------------通用树节点获取功能--------------------------
app.get('/basis_api/treenode/:treeType/:key',function(req,res){
  var sql='select * from '+req.params.treeType+' where id=? and status=1';
  var opt=[req.params.key];
  console.log("SQL:"+sql);
  console.log("OPT:"+JSON.stringify(opt));
   pool.getConnection(function(err,conn){
      if(err)
        console.log('树节点数据取数失败!');
      else
        console.log('树节点数据连接成功！');
      conn.query(sql,opt,function(err,results){
     
     var j={success:true,data:results[0]};
     console.log(j);
      res.send(j);
     });
    conn.release();
});
});

///basis_api/sysinfo/get/:x_id  --------------------------------获取系统信息-------------
app.get('/basis_api/sysinfo/get/:x_id',function(req,res){
  var sql='select * from v_sys_regist where x_id=?';
  var opt=[req.params.x_id];
  console.log("SQL:"+sql);
  console.log("OPT:"+JSON.stringify(opt));
   pool.getConnection(function(err,conn){
      if(err)
        console.log('系统信息数据取数失败!');
      else
        console.log('系统信息数据连接成功！');
      conn.query(sql,opt,function(err,results){
     console.log("数据查询结果："+JSON.stringify(results));
     var j={success:true,data:results[0]};
     console.log(j);
      res.send(j);
     });
    conn.release();
});
});

//-------------------------------------获取组织树XID------------------------
app.get('/basis_api/orgtree/xid/:x_id',function(req,res){
  // function xx(){  //函数开始
  const x_id=req.params.x_id;
  var sql='select * from base_organization where x_id=? order by id ';
  var opt=[x_id];
  pool.getConnection(function(err,conn){
        if(err)  console.log('连接池错误。。。。。');
        else
         console.log('连接池成功。。。。');
    conn.query(sql,opt,function(err,results){
    if(err)
      console.log('生成组织树错误:'+JSON.stringify(err));
    else {
     // console.log(JSON.stringify(results));
     var ctree=buildTreeById(results);
         var j={success:true,data:ctree};  
      console.log('生成组织树数据：'+JSON.stringify(j));
         res.send(j);
     }});
    conn.release();
});

//   }//函数结束

});  

////按传入的组织ID，显示本级和上级信息
app.get('/basis_api/organization/id/:id',function(req,res){
  var sql='select * from v_organization where id=? and status=1';
  var opt=[req.params.id];
  pool.getConnection(function(err,conn){
      if(err)
        console.log('组织数据取数失败!');
      else
        console.log('组织数据连接成功！');
      conn.query(sql,opt,function(err,results){
     var j={success:true,data:results[0]};
     console.log(j);
      res.send(j);
     });
    conn.release();
});
});

///basis_api/orgtree/xid/org/:x_id  ---------------------获取X组织树，仅包含非部门的架构----
app.get('/basis_api/orgtree/xid/org/:x_id',function(req,res){
  // function xx(){  //函数开始
  const x_id=req.params.x_id;
  var sql='select * from base_organization where x_id=? and org_type in(1,2) order by id ';
  var opt=[x_id];
  pool.getConnection(function(err,conn){
        if(err)  console.log('连接池错误。。。。。');
        else
         console.log('连接池成功。。。。');
    conn.query(sql,opt,function(err,results){
    if(err)
      console.log('生成组织树错误:'+JSON.stringify(err));
    else {
     // console.log(JSON.stringify(results));
     var ctree=buildTreeById(results);
         var j={success:true,data:ctree};  
      console.log('生成组织树数据：'+JSON.stringify(j));
         res.send(j);
     }});
    conn.release();
});

//   }//函数结束

});  

 //1连接数据库取数，2再通过内部函数迭代，3生成字串返回------------------注意：本函数生成为表单项使用TreeSelect-----------------------------------
 app.get('/basis_api/treeselect/areatree',function(req,res){
  // function xx(){  //函数开始
        var sql='select * from mes_basis.base_area';
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
         
  //调用函数生成树
           var ctree=buildSelectTree(results);
 
  //返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:true,data:ctree};  
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  

//创建树形结构数据的迭代函数，此处为接收“区域”数据，并生成符合TREE字符串格式返回-----注意：用于表单项ProFormTreeSelect------
function buildSelectTree(rets){
  //最大5层，先分拆为5个数据集，再逐个生成
      var t0=[];
      rets.map((r)=>{
                 if(r.layer===0&&r.status===1)
                     t0.push(r);
                    return;
            });

       var t1=[];
      rets.map((r)=>{
                 if(r.layer===1&&r.status===1)
                     t1.push(r);
                    return;
            });
var t2=[];
      rets.map((r)=>{
                 if(r.layer===2&&r.status===1)
                     t2.push(r);
                    return;
            });
var t3=[];
      rets.map((r)=>{
                 if(r.layer===3&&r.status===1)
                     t3.push(r);
                    return;
            });
var t4=[];
      rets.map((r)=>{
                 if(r.layer===4&&r.status===1)
                     t4.push(r);
                    return;
            });
var t5=[];
      rets.map((r)=>{
                 if(r.layer===5&&r.status===1)
                     t5.push(r);
                    return;
            });
//逐个生成数组对象
var ctree=[];
ctree[0]={value:t0[0].id,label:t0[0].code.concat('  ',t0[0].name),children:[]};
//第1层
t1.map((t)=>{
   ctree[0].children.push({value:t.id,label:t.code.concat('  ',t.name),children:[]});
});
//第2层：需要先定位，再插入
t2.map((t20)=>{
   ctree[0].children.map((c1,index)=>{
       if(t20.higher_id===c1.value)
                ctree[0].children[index].children.push({value:t20.id,label:t20.code.concat('  ',t20.name),children:[]});
    })
})
//第3层：
t3.map((t30)=>{
   ctree[0].children.map((c31,index1)=>{
           ctree[0].children[index1].children.map((c32,index2)=>{
                 if(t30.higher_id===c32.value)
                      ctree[0].children[index1].children[index2].children.push({value:t30.code,label:t30.code.concat('  ',t30.name),children:[]});
    })
})
})
//第4层：
t4.map((t40)=>{
   ctree[0].children.map((c41,index1)=>{
           ctree[0].children[index1].children.map((c42,index2)=>{
                    ctree[0].children[index1].children[index2].children.map((c43,index3)=>{
                 if(t40.higher_id===c43.value)
                      ctree[0].children[index1].children[index2].children[index3].children.push({value:t40.id,label:t40.code.concat('  ',t40.name),children:[]});
    })
})
})
})
//第5层：
t5.map((t50)=>{
   ctree[0].children.map((c51,index1)=>{
           ctree[0].children[index1].children.map((c52,index2)=>{
                    ctree[0].children[index1].children[index2].children.map((c53,index3)=>{
                            ctree[0].children[index1].children[index2].children[index3].children.map((c54,index4)=>{
                 if(t50.higher_id===c54.value)
                      ctree[0].children[index1].children[index2].children[index3].children[index4].children.push({value:t50.id,label:t50.code.concat('  ',t50.name),children:[]});
    })
})
})
})
})
//6层转换结束，应返回值
return ctree;
}

//创建树形结构数据的迭代函数，此处为接收“区域”数据，并生成符合TREE字符串格式返回-----注意：用于表单项TreeSelect------
//----------------注意：不是ProFormTreeSelect----------!!-----------------
function buildSelectTree2(rets){
  //最大5层，先分拆为5个数据集，再逐个生成
      var t0=[];
      rets.map((r)=>{
                 if(r.layer===0&&r.status===1)
                     t0.push(r);
                    return;
            });

       var t1=[];
      rets.map((r)=>{
                 if(r.layer===1&&r.status===1)
                     t1.push(r);
                    return;
            });
var t2=[];
      rets.map((r)=>{
                 if(r.layer===2&&r.status===1)
                     t2.push(r);
                    return;
            });
var t3=[];
      rets.map((r)=>{
                 if(r.layer===3&&r.status===1)
                     t3.push(r);
                    return;
            });
var t4=[];
      rets.map((r)=>{
                 if(r.layer===4&&r.status===1)
                     t4.push(r);
                    return;
            });
var t5=[];
      rets.map((r)=>{
                 if(r.layer===5&&r.status===1)
                     t5.push(r);
                    return;
            });
//逐个生成数组对象
var ctree=[];
ctree[0]={value:t0[0].id,title:t0[0].code.concat('  ',t0[0].name),children:[]};
//第1层
t1.map((t)=>{
   ctree[0].children.push({value:t.id,title:t.code.concat('  ',t.name),children:[]});
});
//第2层：需要先定位，再插入
t2.map((t20)=>{
   ctree[0].children.map((c1,index)=>{
       if(t20.higher_id===c1.value)
                ctree[0].children[index].children.push({value:t20.id,title:t20.code.concat('  ',t20.name),children:[]});
    })
})
//第3层：
t3.map((t30)=>{
   ctree[0].children.map((c31,index1)=>{
           ctree[0].children[index1].children.map((c32,index2)=>{
                 if(t30.higher_id===c32.value)
                      ctree[0].children[index1].children[index2].children.push({value:t30.code,title:t30.code.concat('  ',t30.name),children:[]});
    })
})
})
//第4层：
t4.map((t40)=>{
   ctree[0].children.map((c41,index1)=>{
           ctree[0].children[index1].children.map((c42,index2)=>{
                    ctree[0].children[index1].children[index2].children.map((c43,index3)=>{
                 if(t40.higher_id===c43.value)
                      ctree[0].children[index1].children[index2].children[index3].children.push({value:t40.id,title:t40.code.concat('  ',t40.name),children:[]});
    })
})
})
})
//第5层：
t5.map((t50)=>{
   ctree[0].children.map((c51,index1)=>{
           ctree[0].children[index1].children.map((c52,index2)=>{
                    ctree[0].children[index1].children[index2].children.map((c53,index3)=>{
                            ctree[0].children[index1].children[index2].children[index3].children.map((c54,index4)=>{
                 if(t50.higher_id===c54.value)
                      ctree[0].children[index1].children[index2].children[index3].children[index4].children.push({value:t50.id,title:t50.code.concat('  ',t50.name),children:[]});
    })
})
})
})
})
//6层转换结束，应返回值
return ctree;
}

///basis_api/currency/get/:id --------------------------获取币种信息---------------------------
app.get('/basis_api/currency/get/:id',function(req,res){
  // function xx(){  //函数开始
       const id=req.params.id;
        var sql='select * from currency_type';
        var opt=[];
        if(id!=0){
          sql=sql+' where id=?';
          opt=[id];
        }
           
        pool.getConnection(function(err,conn){
              if(err)  
                 console.log('连接池错误。。。。。');
              else
                 console.log('连接池成功。。。。');
          conn.query(sql,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:true,data:results};  
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  

///basis_api/currency/save  -----------------------保存币种信息----------------
app.post('/basis_api/currency/save',function(req,res){//---1
  var etype=req.body.etype;    
  var operater_id=req.body.operater_id;    
  var fdata=req.body.fdata;
    //  console.log('JSON输出参数值：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
      var sql='call p_savecurrency(?,?,?)';
      var opt=[operater_id,etype,JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。

  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('数据库更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
   });//--1

///basis_api/reason/get/:id --------------------------获取不良信息---------------------------
app.get('/basis_api/reason/get/:x_id/:id',function(req,res){
  // function xx(){  //函数开始
       const id=req.params.id;
       const x_id=req.params.x_id;
        var sql='select * from reason where x_id=? ';
        var opt=[x_id];
        if(id!=0){
          sql=sql+' and  id=?';
          opt=[x_id,id];
        }

        console.log('SQL:'+sql);
        console.log('OPT:'+JSON.stringify(opt));   

        pool.getConnection(function(err,conn){
              if(err)  
                 console.log('连接池错误。。。。。');
              else
                 console.log('连接池成功。。。。');
          conn.query(sql,opt,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
             if(err)
                console.log(JSON.stringify(err));

              var j={success:true,data:results};  
              console.log(JSON.stringify(j));
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  

///basis_api/reason/save  -----------------------保存不良信息----------------
app.post('/basis_api/reason/save',function(req,res){//---1
  var etype=req.body.etype;    
  var operater_id=req.body.operater_id;    
  var fdata=req.body.fdata;
  var x_id=req.body.x_id;
    //  console.log('JSON输出参数值：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
      var sql='call p_savereason(?,?,?,?)';
      var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。

  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('数据库更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
   });//--1

   ///basis_api/sysinfo/update  ----------------------------保存系统信息---------------------------------------
app.post('/basis_api/sysinfo/update',function(req,res){//---1
    const {fdata}=req.body;
    //  console.log('JSON输出参数值：'+JSON.stringify(d2));  //获取参数，注意前端调用request时，要用data:参数对象
    //  res.send({data:'成功更新数据'});
      var sql='call p_updatesysinfo(?)';
      var opt=[JSON.stringify(fdata)];                  //---------将接收的JSON对象传给MYSQL存储过程--注意：必须先转换成字符串，否则会视为多个参数。

      console.log('执行SQL语句：'+sql);
      console.log('执行OPT参数:'+JSON.stringify(opt));
  //先创建连接池，再通过连接执行语句
      pool.getConnection(function(err,conn){   //--2
          if(err)
            console.log('连接池错误');
          else
           console.log('连接数据库成功');
         
      conn.query(sql,opt,function(err,results){   //执行SQL--3
          if(err){
             console.log(err);
           res.end(JSON.stringify({success:false}));
         }
          else{//--4
          //本程序未更新树节点，以后可再优化     
          res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
            console.log('数据库更新成功，恭喜');
        
          }//--4
     });//--3
      conn.release(); 
    } );//连接池结束--2
   });//--1

   ///basis_api/userinfo/freeze/:etype/:id   ----------------冻结或删除用户--------------------------------
   app.get('/basis_api/userinfo/freeze/:etype/:id',function(req,res){    //带参数为组织编号
    const {etype,id}=req.params;
    var sql='update base_person set status=? where id=?';
    var opt=[etype,id];
     
    pool.getConnection(function(err,conn){
         if(err)
            console.log('数据库连接失败');
        else 
            console.log('数据库连接成功');
       conn.query(sql,opt,function(err,results){
        var j={success:true,data:results};
        res.send(j);
         });
     conn.release();
  });
   });

///basis_api/banktable/xid/:x_id/:id   -------------------------获取银行列表-------------------
app.get('/basis_api/banktable/xid/:x_id/:org_id',function(req,res){    //带参数为组织编号
  const x_id=req.params.x_id;
  const org_id=req.params.org_id;
  var sql='select * from v_bank where x_id=? ';
  var opt=[x_id];

  if(org_id!=0){
    sql=sql+' and org_id=? order by id';
    opt=[x_id,org_id];
  }else
    sql=sql+' order by id';

  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      res.send(j);
       });
   conn.release();
});
 });

 //basis_api/base/chanel/operate/:otype/:id -----------操作渠道 2024-10-19----冻结删除--------------
 app.get('/basis_api/base/chanel/operate/:otype/:id',function(req,res){    //带参数为组织编号
  const {otype,id}=req.params;
  var sql='update base_chanel set status=? where id=?';
  var opt=[otype,id];

 pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/shipping/freeze/:type/:id  -----------------------操作船公司-------------------------------
 app.get('/basis_api/shipping/freeze/:type/:id',function(req,res){    //带参数为组织编号
  const {type,id}=req.params;
  var sql='update base_shipping set status=? where id=?';
  var opt=[type,id];
  console.log('操作船公司SQL:'+sql);
  console.log('操作船公司OPT'+JSON.stringify(opt));
 
 pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/base/postware/info/get---------------------------获取邮编-仓库列表------------------------------
 app.post('/basis_api/base/postware/info/get',function(req,res){    //带参数为组织编号
  const {source,x_id,id}=req.body;
  var sql='select * from '+source+' where x_id=? ';
  var opt=[x_id];
  if(id!=0){
    sql=sql+' and id=?';
    opt=[x_id,id];
  }

  console.log('获取邮编SQL:'+sql);
  console.log('获取邮编OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/business/priceschedule/fourdatas/get-------------价格表编辑，获取四项阶梯数据------------------------
 app.post('/basis_api/business/priceschedule/fourdatas/get',function(req,res){    //带参数为组织编号
  //{mid,pricetype_id,chanel_id,inware_id,ware_id,postcode_id}
  const {mid,pricetype_id,chanel_id,inware_id,ware_id,postcode_id}=req.body;
  var sql='call s_getfourdatas(?,?,?,?,?,?)';
  var opt=[mid,pricetype_id,chanel_id,inware_id,ware_id,postcode_id];

  console.log('操作SQL:'+sql);
  console.log('操作OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/base/priceschedule/operate------------------------价格表操作---------------------------------
 app.post('/basis_api/base/priceschedule/operate',function(req,res){    //带参数为组织编号
  //{source:'base_postcode/_group',type:1档案或2组,otype:123,id:具体操作的ID}
  const {mid,pricetype_id,chanel_id,inware_id,ware_id,postcode_id,status,otype}=req.body;
  var sql='call s_operateinfoprice(?,?,?,?,?,?,?,?)';
  var opt=[mid,pricetype_id,chanel_id,inware_id,ware_id,postcode_id,status,otype];

  console.log('操作SQL:'+sql);
  console.log('操作OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
       console.log('查找结果：'+JSON.stringify(j));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/base/query/component------------------------查询基础数据组件专用----------------------------
 app.post('/basis_api/base/query/component',function(req,res){    //带参数为组织编号
  //{source:'base_postcode/_group',type:1档案或2组,otype:123,id:具体操作的ID}
  const {x_id,source,tdata}=req.body;
  var sql='call s_querybasedata(?,?,?)';
  var opt=[x_id,source,JSON.stringify(tdata)];

  console.log('操作SQL:'+sql);
  console.log('操作OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        console.log(JSON.stringify(err));
        res.end();
      }
      else{
      var j={success:true,data:results};
      console.log('查找结果：'+JSON.stringify(j));
      res.send(j);
      }
       });
   conn.release();
});
 });

 ///basis_api/produce/vouch/alloc-------------------------生产下单及派工类 的操作--2025-04-18----------------------
 app.post('/basis_api/produce/vouch/alloc',function(req,res){    //带参数为组织编号
  //{source:'base_postcode/_group',type:1档案或2组,otype:123,id:具体操作的ID}
  const {x_id,operater_id,vtype,tdata}=req.body;
  var sql='call p_produce2alloc(?,?,?,?)';
  var opt=[x_id,operater_id,vtype,JSON.stringify(tdata)];

  console.log('操作SQL:'+sql);
  console.log('操作OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err){
          console.log('数据库连接失败');
          res.end({success:false,error:err});
       }
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        console.log(JSON.stringify(err));
        res.end({success:false,error:err});
      }
      else{
      var j={success:true,data:results};
      console.log('查找结果：'+JSON.stringify(j));
      res.send(j);
      }
       });
   conn.release();
});
 });

 //basis_api/common/table/operate  ---------------------------通用表格操作-带明细参数-2025-01-04----------------------------------
 app.post('/basis_api/common/table/operate',function(req,res){    //带参数为组织编号
  //{source:'base_postcode/_group',type:1档案或2组,otype:123,id:具体操作的ID}
  const {source,x_id,operater_id,etype,otype,id,tdata}=req.body;
  var sql='call p_operate2data(?,?,?,?,?,?,?)';
  var opt=[source,x_id,operater_id,etype,otype,id,JSON.stringify(tdata)];

  console.log('操作SQL:'+sql);
  console.log('操作OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
          if(err){
            console.log(err);
            return {success:false,error:err}
          }
          else{
             var j={success:true,data:results};
               //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
              res.send(j);
          };

       });
   conn.release();
   return ;
});
 });


 ///basis_api/base/table/operate  -----------------------通用表格操作  2024-10-21-------冻结删除----------------------
 app.post('/basis_api/base/table/operate',function(req,res){    //带参数为组织编号
  //{source:'base_postcode/_group',type:1档案或2组,otype:123,id:具体操作的ID}
  const {source,x_id,operater_id,otype,id,ids}=req.body;
  var sql='call s_operateinfo(?,?,?,?,?)';
  var opt=[source,x_id,operater_id,otype,id];
  
  if(source=='purchase_vendor_price'){
     var sql='call s_operateinfo2(?,?,?,?,?)';
  var opt=[source,x_id,operater_id,otype,ids];
  };

  // stock_out_apply_main  当拣货单/生产+外发，审核时自动生成已审核的材料出库单。
  //in px_id int,in poperater_id int,in etype int,in source varchar(50),in tdata text character set utf8
  if(source=='stock_out_apply_main_verify'){
     var sql='call p_stock_out(?,?,?,?,?)';
  var opt=[,x_id,operater_id,otype,source,JSON.stringify({id})];
  };

  
  console.log('操作SQL:'+sql);
  console.log('操作OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 //basis_api/base/table/update-------------------表格保存的通用程序----------------------
 app.post('/basis_api/base/table/update',function(req,res){    //带参数为组织编号
  //{source:表名，x_id,operater_id,etype:0编辑1新增,fdata}
  const {source,x_id,operater_id,etype,fdata}=req.body;
  var sql='call s_updateinfo(?,?,?,?,?)';
  var opt=[source,x_id,operater_id,etype,JSON.stringify(fdata)];

  console.log('通用数据更新SQL:'+sql);
  console.log('通用数据更新OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        console.log(err);
        res.send({success:false,data:null});
      }else{
        var j={success:true,data:results};
        console.log(source+'通用数据更新：'+JSON.stringify(j));
        res.send(j);
      };
       });
   
   conn.release();
});
 });

//basis_api/produce/table/update-----------------生产模块--表格保存的通用程序--2025-04-28--------------------
app.post('/basis_api/produce/table/update',function(req,res){    //带参数为组织编号
  //{source:表名，x_id,operater_id,etype:0编辑1新增,fdata}
  const {source,x_id,operater_id,etype,fdata}=req.body;
  var sql='call p_produce_updateinfo(?,?,?,?,?)';
  var opt=[source,x_id,operater_id,etype,JSON.stringify(fdata)];

  console.log('通用数据更新SQL:'+sql);
  console.log('通用数据更新OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err){
          console.log('数据库连接失败');
          res.send({success:false,error:err});
        }else{
            console.log('数据库连接成功');
            conn.query(sql,opt,function(err,results){
            if(err){
                console.log(err);
                res.send({success:false,data:err});
            }else{
                 console.log('全量返回值数据：'+JSON.stringify(results));
                 //   if(source=='produce_order_byverify'){
                 //      console.log('9999');
                 var state=results[0]&&results[0][0].state?results[0][0].state:'0';
                 // console.log(state);
                 var j;
                 if(source=='produce_order_byverify'&&state!=undefined&&(state==0||state=='0')){ 
                     j={success:0,err:'错误！以下商品未维护默认工艺流程：'+JSON.stringify(results[1])};
                     res.send(j);
                     console.log(JSON.stringify(j));
                }
                else{
        //     var m={success:true,data:results};
        //     console.log(source+'自动生成生产单成功：'+JSON.stringify(m));
        //     res.send(m);
        //  };
        //  console.log('kkkkk');

        //  }else{
          
                 j={success:true,data:results};
                 console.log(source+'数据操作更新成功：'+JSON.stringify(j));
                 res.send(j);
        //  };
          };
         };
         
       });
       };

  //  console.log('+++++++++++');
      
   conn.release();
   
});

 });


 //basis_api/purchase/table/update-----------------采购模块--表格保存的通用程序--2025-05-24------------------
app.post('/basis_api/purchase/table/update',function(req,res){    //带参数为组织编号
  //{source:表名，x_id,operater_id,etype:0编辑1新增,fdata}
  const {source,x_id,operater_id,etype,fdata}=req.body;
  var sql='call p_purchase_updateinfo(?,?,?,?,?)';
  var opt=[source,x_id,operater_id,etype,JSON.stringify(fdata)];

  console.log('通用数据更新SQL:'+sql);
  console.log('通用数据更新OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err){
          console.log('数据库连接失败');
          res.send({success:false,error:err});
        }
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        console.log(err);
        res.send({success:0,data:null});
      }else{
        var j={success:true,data:results};
        console.log(source+'通用数据更新：'+JSON.stringify(j));
        res.send(j);
      };
       });
   
   conn.release();
});
 });



 ///basis_api/base/postware/update  -------------------------更新邮编或仓库组，两者通用-------------------------
 app.post('/basis_api/base/postware/update',function(req,res){    //带参数为组织编号
  //{source:表名，x_id,operater_id,etype:0编辑1新增,fdata}
  const {source,x_id,operater_id,etype,fdata}=req.body;
  var sql='call s_updateinfo(?,?,?,?,?)';
  var opt=[source,x_id,operater_id,etype,JSON.stringify(fdata)];

  console.log('保存邮编仓库SQL:'+sql);
  console.log('保存邮编仓库OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err)
        console.log(err);
      
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
       
   conn.release();
});
 });

//basis_api/shipping/info/save  -------------------------------保存船公司信息-----------------------------
app.post('/basis_api/shipping/info/save',function(req,res){    //带参数为组织编号
  const {x_id,operater_id,etype,fdata}=req.body;
  var sql='call s_saveshippinginfo(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];

  console.log('保存船公司SQL:'+sql);
  console.log('保存船公司OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/shippingperiod/info/get--------------获取船期表主表数据---------------------------------------
 app.post('/basis_api/shippingperiod/info/get',function(req,res){    //带参数为组织编号
  const {type,tdata}=req.body;
  var sql='call s_getshippingperiod(?,?)';
  var opt=[type,JSON.stringify(tdata)];
  
  console.log('船期表取数SQL:'+sql);
  console.log('船期表取数OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err)
        console.log(err);
      var j={success:true,data:results};
       console.log('获取船期表数据：'+JSON.stringify(j));
      res.send(j);
       });
   conn.release();
});
 });

 //basis_api/table/info/detail/get
 //basis_api/table/info/detail/get  -------------------------通用表格取数,取明细表数据 2024-10-20---3个参数-------------------------
 app.post('/basis_api/table/info/detail/get',function(req,res){    //带参数为组织编号
  const {source,x_id,mid}=req.body;
  var sql='select * from '+source+' where 1=1 ';
   if(x_id!=0&&mid==0){
     sql=sql+' and x_id=?';
     opt=[x_id];
   };
   if(x_id==0&&mid!=0){
    sql=sql+' and mid=?';
    opt=[mid];
  };
  if(x_id==0&&mid==0){
    sql=sql+' and x_id=? and mid=?';
    opt=[x_id,mid];
  }
 
  if(source=='v_sale_order_detail2')
     sql=sql+' and status not in(2,3)';

  console.log('通用表格取数SQL:'+sql);
  console.log('通用表格取数OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });


// /basis_api/require/planning---------------------------------计算需求计划2025-03-28------------------------------------------------
app.post('/basis_api/require/planning',function(req,res){    //带参数为组织编号
  const {x_id,operater_id,fdata}=req.body;
  var sql='call p_require_caculate(?,?,?)';
  var opt=[x_id,operater_id,JSON.stringify(fdata)];
  
  console.log('需求计算SQL:'+sql);
  console.log('需求计算OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        console.log(err);
        res.send({success:false,data:null});
      };
      var j={success:true,data:results};
       console.log('返回已计算好的需求数据：'+JSON.stringify(j));
      res.send(j);
       });
    // res.end();
   conn.release();
});
 });

 //basis_api/table/info/get  -------------------------通用表格取数  2024-10-20---3个参数-------------------------
 app.post('/basis_api/table/info/get',function(req,res){    //带参数为组织编号
  const {source,x_id,id,type}=req.body;
  var sql='select * from '+source+' where x_id=?';
  var opt=[x_id];

  if(id!=0){
    sql=sql+(source=='v_userdefineapply'?' and material_id=?'
             :source=='v_material_code_custom'?' and material_id=?'
             :source=='v_workgroup_param'?' and workgroup_id=?'
             :source=='v_craft_card_detail'?' and card_id=?'
             :source=='v_craft_card_option'?' and card_id=?'
             :source=='v_material_craft_route_card_bom'?' and card_mid=?'
             :source=='v_warehouse_pos'?' and warehouse_id=?':' and id=?');
    opt=[x_id,id];
  }
  
  if(source=='sample_detail'){
    sql='select * from '+source+' where x_id=? and mid=?';  //注意前端传来的id，实际对应mid即主表id
    opt=[x_id,id];
  }

  if(source=='v2_order_main'){
    sql='select * from v2_order_main where state not in(1,9) and x_id=?';
    opt=[x_id];
  }

  if(source=='material_param'){
    sql='select * from material_param where material_id=?';
    opt=[id];
  }

  if(source=='v_bom_detail'){
    sql='select * from v_bom_detail where mid=?';
    opt=[id];
  }

  if(source=='produce_pricerate_main'){
    sql='select * from produce_pricerate_main where x_id=? order by id desc';
    opt=[x_id];
  }

  if(source=='v_require_caculate')
    sql=sql+' order by operate_time,order_code';

  if(source=='taskcard_reporting')
    sql='select * from v_taskcard_reporting where x_id='+x_id+' and taskcard_sno="'+id+'"';

  if(source=='taskcard_reporting2')
    sql='select * from v_taskcard_reporting2 where x_id='+x_id+' and taskcard_sno="'+id+'"';
  //2025-05-19销售备料单，和销售发货单分开下达，只有类型不一样
  

  console.log('通用表格取数SQL:'+sql);
  console.log('通用表格取数OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 //basis_api/basedata/chanel/unallocate/get  -------------------------获取未分配组的渠道-------------------------
 app.post('/basis_api/basedata/chanel/unallocate/get',function(req,res){    //带参数为组织编号
  const {x_id,mid}=req.body;
  var sql='select * from v_chanellist where x_id=? and status=1 and id not in(select chanel_id from v_chanelgroups where mid=?)';
  var opt=[x_id,mid];
  
  console.log('通用表格取数SQL:'+sql);
  console.log('通用表格取数OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/basedata/chanel/allocate/save ------------------保存渠道组分配信息-----------------------------------
 app.post('/basis_api/basedata/chanel/allocate/save',function(req,res){    //带参数为组织编号
  const {x_id,mid,id}=req.body;
  var sql='call p_allocatechanel(?,?,?)';
  var opt=[x_id,mid,id];
  
  console.log('分配渠道SQL:'+sql);
  console.log('分配渠道OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
          res.send({success:false,error:err});
      }else{
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
      }
       });
   conn.release();
});
 });

 //p_allocatechanelupdate  -------------操作渠道分配------------------2024-11-07--------
 app.post('/basis_api/basedata/chanel/allocate/operate',function(req,res){    //带参数为组织编号
  const {x_id,otype,id}=req.body;
  var sql='call p_allocatechanelupdate(?,?,?)';
  var opt=[x_id,otype,id];
  
  console.log('分配渠道SQL:'+sql);
  console.log('分配渠道OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
          res.send({success:false,error:err});
      }else{
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
      }
       });
   conn.release();
});
 });

//basis_api/shipping/info/get    ------------------------------获取船公司信息-----------------------------
app.post('/basis_api/shipping/info/get',function(req,res){    //带参数为组织编号
  const {x_id,id}=req.body;
  var sql='select * from v_shipping where x_id=?';
  var opt=[x_id];
  if(id!=0){
    sql=sql+' and id=?';
    opt=[x_id,id];
  }
  
  console.log('船公司SQL:'+sql);
  console.log('船公司OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 ///basis_api/priceschedule/main/get--------------------------------获取价格表主目录 --------------
 app.post('/basis_api/priceschedule/main/get',function(req,res){    //
  const {x_id,mid,chanelcategory_id,chanel_id,inware_id,outware_id,outpostcode_id,status,operate_time,postcodegroup_id,status2}=req.body;
  var sql='call p_getpriceschedule_main(?,?,?,?,?,?,?,?,?,?,?)';
  var opt=[x_id,mid,chanelcategory_id,chanel_id,inware_id,outware_id,outpostcode_id,status,status2,JSON.stringify(operate_time),postcodegroup_id];
    
  console.log('获取海卡价格表SQL:'+sql);
  console.log('获取海卡价格表OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
           console.log(err);
           res.send({success:false,data:null});
           
       }else{
           var j={success:true,data:results};
          // console.log(JSON.stringify(j));
           res.send(j);
           
       }
       });
   conn.release();
     });
     return;
 });

 //basis_api/priceschedule/get--------------------------------------获取价格表明细-2024-10-23--------------------------
 app.post('/basis_api/priceschedule/get',function(req,res){    //
  const {x_id,mid,chanelcategory_id,chanel_id,inware_id,outware_id,outpostcode_id,status,status2,operate_time}=req.body;
  var sql='call p_getpriceschedule(?,?,?,?,?,?,?,?,?,?)';
  var opt=[x_id,mid,chanelcategory_id,chanel_id,inware_id,outware_id,outpostcode_id,status,status2,JSON.stringify(operate_time)];
    
  console.log('获取海卡价格表SQL:'+sql);
  console.log('获取海卡价格表OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
           console.log(err);
           res.send({success:false,data:null});
          
       }else{
           var j={success:true,data:results};
           console.log(JSON.stringify(j));
           res.send(j);
       }
       });
      conn.release();
      return ; 
     });
     return;
 });

///basis_api/select/get/:x_id/:source ------------------------------按表名获取下拉列表------------------------------
app.get('/basis_api/select/get/:x_id/:source',function(req,res){   
  const {x_id,source,param}=req.params;
  var sql='select distinct  id,name from '+source+' where x_id=? and status=1';
  var opt=[x_id];

  if(source=='base2_ware')
      sql='select distinct  id,name from base_ware where x_id=? and status=1';
  

  if(source.includes('base_ware')){//仓库需区分进货、到货仓，特殊处理
      var source2=source.toString().substring(0,source.toString().length-1);
      var type=source.toString().substring(source.toString().length-1);
      sql='select distinct  id,name from '+source2+' where x_id=? and status=1 and type=?';
      opt=[x_id,type];
  }

  if(source.includes('base_postcode_group')){//邮编组需返回多项数据，特殊处理
      sql='select distinct  id,concat(name,groups) as name from base_postcode_group where x_id=? and status=1';
     opt=[x_id];
  }

  if(source.includes('base_weightrate_group')){//比重组需返回多项数据，特殊处理
    sql='select distinct  id,groups as name from base_weightrate_group where x_id=? and status=1';
   opt=[x_id];
}
  //按工艺流程取下拉框时，同时返回版本列表
  if(source=='craft_route'){
      sql='select distinct  id,concat(name,version) as name from craft_route where x_id=? and status=1';
      opt=[x_id];
  } 
   
  if(source=='base_intype'){
     sql='select distinct  id,name from base_iotype where x_id=? and type=1 and status=1';
     opt=[x_id];
  }

  if(source=='base_outtype'){
    sql='select distinct  id,name from base_iotype where x_id=? and type=2 and status=1';
    opt=[x_id];
 }

 //带入查询的值---实现模糊查询，用于下拉框选择--用于计件工资。新KSU码选择
  if(source.indexOf('material_')==0){
         sql='select id,concat(code,"   ",name) as name from v_material where x_id=? and (code like concat("%",?,"%") or name like concat("%",?,"%"))';
         opt=[x_id,source.substring(source.indexOf('_')+1),source.substring(source.indexOf('_')+1)];
     };

if(source.indexOf('_material')>0){
      sql='select id,concat(code," ",name) as name from v_material where x_id=? and id=? ';
      opt=[x_id,source.substring(0,source.indexOf('_material'))];
  };

  if(source=='vmaterial'){
      sql='select id,concat(code," ",name) as name from v_material where x_id=?';
      opt=[x_id];
  };

  //拣货位置设置，库位编码以JH开头。
  if(source=='jh_whposition'){
      sql='select id,concat(code," ",name) as name from base_warehouse_pos where x_id=? and code like "'+'JH%'+'"';
      pt=[x_id];
  }

  console.log('下拉框SQL：'+sql);
  console.log('下拉框OPT'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');

     conn.query(sql,opt,function(err,results){
      if(err)
        console.log(err);
      else{
      //组装为[{label,value}]
      var d=[];
      results.map((item)=>d.push({label:item.name,value:item.id}));
      var j={success:true,data:d};
      
      console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
      };
       });
      
   conn.release();
});
 });

 ///basis_api/select/get/bycondition ------ -按表名获取下拉列表:带条件--2025-03-25----------------------------
app.post('/basis_api/select/get/bycondition',function(req,res){   
  const {x_id,source,fdata}=req.body;
      
  if(source=='bomVersion'){
      console.log(fdata);
      var material_id=fdata.material_id;
      sql='select id,concat("V",version,"-",memo) as name from bom_main where material_id=? and x_id=? and status not in(2,3)';
      opt=[material_id,x_id];
  };

  if(source=='v_material'){
    var value=fdata.value;
    sql='select  id,concat(name,invstd)  as name from v_material where status=1 and x_id=? and lower(name)  like  concat("%",lower('+value+'),"%") limit 10';
    opt=[x_id];
};

  console.log('下拉框SQL：'+sql);
  console.log('下拉框OPT'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      //组装为[{label,value}]
      var d=[];
      if(results&&results.length>0)
          results.map((item)=>d.push({label:item.name,value:item.id}));
      else 
          console.log('没有对应的下拉数据');
      var j={success:true,data:d};
      console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
       });
   conn.release();
});
 });

 //basis_api/base/chanel/save--------------保存渠道更新信息 2024-10-19------------------------------
 app.post('/basis_api/base/chanel/save',function(req,res){//---1
  //var d2=req.body.paramm;
 const {x_id,operater_id,etype,fdata}=req.body;

//  res.send({data:'成功更新数据'});
  var sql='call p_savechanelinfo(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

 ///basis_api/chanel/info/get-------------获取渠道列表，两个参数：类别keys，渠道id:0为全部------2024-10-18--------
 app.post('/basis_api/chanel/info/get',function(req,res){//---1
  //var d2=req.body.paramm;
 const {x_id,categoryids,id}=req.body;

//  res.send({data:'成功更新数据'});
  var sql='call p_getchanelinfo(?,?,?)';
  var opt=[x_id,id,JSON.stringify(categoryids)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});

 ////保存银行新增或更新------------------保存仓库信息--开始----------------------------------------------
app.post('/basis_api/bank/save',function(req,res){//---1
  //var d2=req.body.paramm;
  const  etype=req.body.etype; // 1新增 ，0修改
  const  fdata=req.body.fdata
  const  x_id=req.body.x_id;
  const  operater_id=req.body.operater_id;

//  res.send({data:'成功更新数据'});
  var sql='call p_savebank(?,?,?,?)';
  var opt=[x_id,operater_id,etype,JSON.stringify(fdata)];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('JSON输出SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('传入数据OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
                
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});


//-------------------------------------获取通用树结构 XID------------------------
app.get('/basis_api/comm/tree/xid/:x_id/:source_table',function(req,res){
   
  const {x_id,source_table}=req.params;

  var sql=('').concat('select * from ',source_table,' where x_id=? and status=1 order by id ');
  var opt=[x_id];

  console.log('SQL语句：'+sql);
  console.log('OPT参数：'+JSON.stringify(opt));

  pool.getConnection(function(err,conn){
        if(err) 
            console.log('连接池错误。。。。。');
        else
            console.log('连接池成功。。。。');
    conn.query(sql,opt,function(err,results){
    if(err)
      console.log('生成组织树错误:'+JSON.stringify(err));
    else {
     // console.log(JSON.stringify(results));
     var ctree=buildTreeById(results);
     var keys=results.map(item=>item.id);
         var j={success:true,data:{ctree,keys}};  
      console.log('生成组织树数据：'+JSON.stringify(j));
         res.send(j);
     }});
    conn.release();
});

//   }//函数结束

});  


//1连接数据库取数，2再通过内部函数迭代，3生成字串返回------注意：本函数生成为表单项使用TreeSelect---不是ProFormTreeSelect------------------------
app.get('/basis_api/treeselect/orgtree/byid/:x_id/:type',function(req,res){
  // function xx(){  //函数开始
        const x_id=req.params.x_id;
        const type=req.params.type;  //1组织，2部门（全部）
        var sql='select * from  base_organization where x_id=? ';
        var opt=[x_id];
        if(type==1)
          sql=sql+' and org_type in(1,2)';
        console.log('获取组织下拉框：SQL'+sql);
        console.log('获取组织下拉框：OPT'+JSON.stringify(opt));
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,opt,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
         
  //调用函数生成树
           var ctree=buildSelectTree2(results);
 
  //返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:true,data:ctree};  
              console.log('组织下拉框数据：'+JSON.stringify(j));
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  

  //1连接数据库取数，2再通过内部函数迭代，3生成字串返回----2024-10-21
  //--注意：本函数生成为表单项使用TreeSelect---不是ProFormTreeSelect-通用选择树-----------------------
app.get('/basis_api/treeselect/common/:x_id/:source',function(req,res){
  // function xx(){  //函数开始
        const x_id=req.params.x_id;
        const source=req.params.source;  
        var sql='select * from '+source+' where x_id=? ';
        var opt=[x_id];
        
        console.log('通用下拉选择框：SQL'+sql);
        console.log('通用下拉选择框：OPT'+JSON.stringify(opt));
        pool.getConnection(function(err,conn){
              if(err)  console.log('连接池错误。。。。。');
              else
               console.log('连接池成功。。。。');
          conn.query(sql,opt,function(err,results){
        //返回数据，要用对象，且包含data或其他接口规范的数据
         
  //调用函数生成树
           var ctree=buildSelectTree2(results);
 
  //返回数据，要用对象，且包含data或其他接口规范的数据
              var j={success:true,data:ctree};  
              console.log('通用下拉选择框数据：'+JSON.stringify(j));
               res.send(j);
           });
          conn.release();
     });
    
 //   }//函数结束
 
  });  


//-------------------------------------获取客商分类的信息---------------------------------
app.get('/basis_api/businesscategory/get/:id',function(req,res){
  var id=req.params.id;
  var sql='select * from v_businesscategory '
  var opt=[];
 
  if(id!=0){   //0默认为全部
   sql=sql+' where id=? order by id';
   opt=[id];
 }

console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

//var params = url.parse(req.url, true).query;------------解析程序URL参数  --小程序价格表---
 app.post('/basis_api/miniprogram/price/query',function(req,res){
  var params = req.body;
  const {px_id,pchanelcategory_id,pchanelgroup_id,parea_id,outware_code,outpostcode_code}=params;
  //px_id,pchanelcategory_id,pchanel_id,pinware_id,outware_id,outpostcode_id
  var sql='call p_mini_getpriceschedule(?,?,?,?,?,?)'
  var opt=[px_id,pchanelcategory_id,pchanelgroup_id,parea_id,outware_code,outpostcode_code];
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

//小程序------------------------------查询船期表-2024-10-30------------------------------
app.post('/basis_api/miniprogram/shipping/query',function(req,res){
  //px_id,pchanel_id,parea_id
  var params = req.body;
  const {px_id,pchanelgroup_id,parea_id}=params;
  //px_id,pchanelcategory_id,pchanel_id,pinware_id,outware_id,outpostcode_id
  var sql='call p_mini_getshippingperiod(?,?,?)'
  var opt=[px_id,pchanelgroup_id,parea_id];
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

//小程序------------------------------查询邮编表-2024-10-30------------------------------
app.post('/basis_api/miniprogram/postcode/query',function(req,res){
  //px_id,pcountry,pprovince,pcity,pware_code
  var params = req.body;
  const {px_id,ppostcode_code,pware_code}=params;
  //px_id,pchanelcategory_id,pchanel_id,pinware_id,outware_id,outpostcode_id
  var sql='call p_mini_getpostcode(?,?,?)'
  var opt=[px_id,pware_code,ppostcode_code];
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 
//小程序 ------------------------------------初始化时载入渠道，为全局变量---------------------------
app.post('/basis_api/miniprogram/chanel/loading',function(req,res){
  //px_id,pcountry,pprovince,pcity,pware_id
  var params = req.body;
  const {px_id,chanel_name}=params;
  //px_id,pchanelcategory_id,pchanel_id,pinware_id,outware_id,outpostcode_id
  var sql='call p_mini_getloading_chanel(?,?)'
  var opt=[px_id,chanel_name];
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 
//小程序 ------------------------------------初始化时载入其他参数项/仓库、邮编等---------------------------
app.post('/basis_api/miniprogram/other/loading',function(req,res){
  //px_id,pcountry,pprovince,pcity,pware_id
  var params = req.body;
  const {px_id,ptype,input_name}=params;
  //px_id,pchanelcategory_id,pchanel_id,pinware_id,outware_id,outpostcode_id
  var sql='call p_mini_getloading_other(?,?,?)'
  var opt=[px_id,ptype,input_name];
  if(ptype==5)
     opt=[px_id,ptype,JSON.stringify(input_name)];//类型5为国家省市，input_name为数组
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/miniprogram/login/count-----------------小程序：记录登录次数/价格表load---2024-11-14-------------------           
app.post('/basis_api/miniprogram/login/count',function(req,res){
  const {px_id,pmodel}=req.body;
  var sql='call p_mini_logincount(?,?)';
  var opt=[px_id,pmodel];
 
console.log('获取小程序登录次数SQL语句：'+sql);
console.log('获取小程序登录次数OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results[0]};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/upload/file/price------------------------------------文件上传-基本设置---------------------------------
var filename='';
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'c:/uploads') // 文件存储路径
  },
    filename: function (req, file, cb) {
     //  cb(null, file.fieldname) // 文件命名
    // console.log(Buffer.from(file.originalname, 'latin1').toString('utf-8'));
     cb(null,Buffer.from(file.originalname,'latin1').toString('utf-8'));
     filename=Buffer.from(file.originalname,'latin1').toString('utf-8');
     console.log('上传的文件名：'+filename);
    }
})
const upload = multer({ storage: storage });
//-------------------------------------------------------------------海卡价格表上传=---2024-11-25--------------------------
app.post('/basis_api/upload/file/price',upload.single('upfile'),function(req,res){
    
  const {x_id,operater_id,begindate,chanelcategory_id}=req.body;
 //console.log(x);
  // var y=Buffer.from(x.toString());
 //  console.log('2.文件大小 ：'+y.length);
 console.log('文件名2:'+filename);
  // res.end();
  //读取刚导入的EXCEL文档，并返回结果
  const workbook=xlsx.readFile('c:/uploads/'+filename);
  console.log('导入文件名：'+'c:/uploads/'+filename);
   const sheetnames=workbook.SheetNames;
   console.log(JSON.stringify(sheetnames));
   //-------------清理数据-----2024-11-19-------------------------------
   var newdata=[];//全部sheet的总表

   sheetnames.map((item)=>{ //for -1 begin
       var sheet = workbook.Sheets[item];
       var data = xlsx.utils.sheet_to_json(sheet)
      // console.log(item+'原始数据：'+JSON.stringify(data));
       var newobj={};//单个sheet对象，含sheetname表名+data明细{sheetname:XXX,data:[...]}
       var newdata2=[];//多个表格行对象的集合
       //将data转换列句及值--如12KG+列，转为weight：12+价格
       var batch_id=1;
       data.map((item2)=>{ //for -2 begin
          var cols=Object.keys(item2);
          cols.map((item3)=>{//for 3 begin
             if(item3.indexOf('KG+')>0){//重量-单价
                  var newobj2={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
                  newobj2['weight']=item3.substring(0,item3.indexOf('KG'));
                  newobj2['price']=item2[item3]==0?0:item2[item3];
                  newobj2['ware_code']=item2['仓库代码'];
                  newobj2['inware_name']=item2['进货仓'];
                  newobj2['batch_id']=batch_id;
                  newdata2.push(newobj2);
              }
              if(item3.indexOf('KG+')==-1&&item3.indexOf('+')>0){//体积-单价
                var newobj2={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
                newobj2['volumn']=item3.substring(0,item3.indexOf('+'));
                newobj2['vprice']=item2[item3]==0?0:item2[item3];
                newobj2['ware_code']=item2['仓库代码'];
                newobj2['inware_name']=item2['进货仓'];
                newobj2['batch_id']=batch_id;
                newdata2.push(newobj2);
            }
          }); //for 3 end
          batch_id+=1;
      });//for -2 end
      newobj['data']=newdata2;
      newobj['sheetname']=item;
      newdata.push(newobj);
   });//for -1 end
    
  // console.log('清理后的数据：'+Buffer.from(JSON.stringify(newdata),'latin1').toString('utf8'));
  //------------------------------------------插入数据库------------------------------------------
  var sql='call p_import_price(?,?,?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)];
  console.log("上传文件参数："+ opt );
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results[0]};
        console.log('海卡数据：'+JSON.stringify(j));
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
   
}); 

//-------------------------------------------------------------------海派价格表上传-2024-11-27----------------------
app.post('/basis_api/upload/file/price2',upload.single('upfile'),function(req,res){
    
  const {x_id,operater_id,begindate,chanelcategory_id}=req.body;
 //console.log(x);
  // var y=Buffer.from(x.toString());
 //  console.log('2.文件大小 ：'+y.length);
 console.log('海卡文件名:'+filename);
  // res.end();
  //读取刚导入的EXCEL文档，并返回结果
  const workbook=xlsx.readFile('c:/uploads/'+filename);
  console.log('导入海卡文件名：'+'c:/uploads/'+filename);
   const sheetnames=workbook.SheetNames;
   console.log(JSON.stringify(sheetnames));
   //-------------清理数据-----2024-11-19-------------------------------
   var newdata=[];//全部sheet的总表

   sheetnames.map((item)=>{ //for -1 begin
       var sheet = workbook.Sheets[item];
       var data = xlsx.utils.sheet_to_json(sheet)
       var newobj={};//单个sheet对象，含sheetname表名+data明细{sheetname:XXX,data:[...]}
       var newdata2=[];//多个表格行对象的集合
       //将data转换列句及值--如12KG+列，转为weight：12+价格
       var batch_id=1;
       data.map((item2)=>{ //for -2 begin
          var cols=Object.keys(item2);
          cols.map((item3)=>{//for 3 begin
             if(item3.indexOf('KG+')>0){//重量-单价
                  var newobj2={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
                  newobj2['weight']=item3.substring(0,item3.indexOf('KG'));
                  newobj2['price']=item2[item3];
                  newobj2['postcodegroup']=item2['邮编开头'];
                  newobj2['area_name']=item2['地区'];
                  newobj2['batch_id']=batch_id;
                  newdata2.push(newobj2);
              }
              if(item3.indexOf('CBM+')>0){//体积-单价
                var newobj2={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
                newobj2['volumn']=item3.substring(0,item3.indexOf('CBM'));
                newobj2['vprice']=item2[item3];
                newobj2['postcodegroup']=item2['邮编开头'];
                newobj2['area_name']=item2['地区'];
                newobj2['batch_id']=batch_id;
                newdata2.push(newobj2);
            }
          }); //for 3 end
          batch_id+=1;
      });//for -2 end
      newobj['data']=newdata2;
      newobj['sheetname']=item;
      newdata.push(newobj);
   });//for -1 end
    
  // console.log('清理后的数据：'+Buffer.from(JSON.stringify(newdata),'latin1').toString('utf8'));
  //------------------------------------------插入数据库------------------------------------------
  var sql='call p_import_price2(?,?,?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)];
  console.log("海派上传文件参数："+ opt );
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results[0]};
        console.log('海派上传数据：'+JSON.stringify(j));
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
   
}); 

///basis_api/upload/file/shipping------------------------导入船期表---2024-11-27----------------------------------
app.post('/basis_api/upload/file/shipping/period',upload.single('upfile'),function(req,res){
  const {x_id,operater_id,begindate}=req.body;
 //console.log(x);
  // var y=Buffer.from(x.toString());
 //  console.log('2.文件大小 ：'+y.length);
 console.log('船期表文件名:'+filename);
  // res.end();
  //读取刚导入的EXCEL文档，并返回结果
  const workbook=xlsx.readFile('c:/uploads/'+filename);
   console.log('导入船期表文件名：'+'c:/uploads/'+filename);
   const sheetnames=workbook.SheetNames;
   console.log(JSON.stringify(sheetnames));
   //-------------清理数据-----2024-11-19-------------------------------
   var newdata=[];//全部sheet的总表
   sheetnames.map((item)=>{ //for -1 begin --只有一个sheet1,循环备用。
       var sheet = workbook.Sheets[item];
       var data = xlsx.utils.sheet_to_json(sheet)
       data.map((item2)=>{ //for -2 begin
          var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
          //渠道	船公司	航名航次	区域	截收时间	预计开船	预计到港	下一水预计时间
          newobj['chanelgroup_name']=item2['渠道组']
          newobj['shipping_name']=item2['船公司'];
          newobj['hcname']=item2['航名航次'];
          newobj['area_name']=item2['区域'];
          newobj['enddingdate']=item2['截收时间'];
          newobj['setoutdate']=item2['预计开船'];
          newobj['reachdate']=item2['预计到港'];
          newobj['nextdate']=item2['下一水预计时间'];
          //按行生成对象，并加入数组
          newdata.push(newobj);
      });//for -2 end
   });//for -1 end
    
  // console.log('清理后的数据：'+Buffer.from(JSON.stringify(newdata),'latin1').toString('utf8'));
  //------------------------------------------插入数据库------------------------------------------
  var sql='call p_import_shippingperiod(?,?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,operater_id,begindate,JSON.stringify(newdata)];
  console.log("船期表上传文件参数："+ opt );
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString());
            }
        else{
        var j={success:true,data:results[0]};
        console.log('船期表上传数据成功。');
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
   
}); 
 
///basis_api/upload/file/warepostcode-------------------------导入地址邮编信息2024-11-27--------------------
app.post('/basis_api/upload/file/warepostcode',upload.single('upfile'),function(req,res){
  const {x_id,operater_id}=req.body;
  console.log('地址邮编文件名:'+filename);
  // res.end();
  //读取刚导入的EXCEL文档，并返回结果
  const workbook=xlsx.readFile('c:/uploads/'+filename);
   console.log('导入船期表文件名：'+'c:/uploads/'+filename);
   const sheetnames=workbook.SheetNames;
   console.log(JSON.stringify(sheetnames));
   //-------------清理数据-----2024-11-19-------------------------------
   var newdata={};//全部
   var wares=[];//地址仓库
  //  var isfars=[];//是否偏远
  // sheetnames.map((item)=>{ //for -1 begin --只有一个sheet1,循环备用。
  //先导入邮编
       var sheet = workbook.Sheets["地址邮编"];
       var data = xlsx.utils.sheet_to_json(sheet)
       data.map((item2)=>{ //for -2 begin
          var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
          //ware_code,country,province,city,address,postcode,company
          newobj['ware_code']=item2['仓库代码']
          newobj['country']=item2['国家'];
          newobj['province']=item2['省洲'];
          newobj['city']=item2['城市'];
          newobj['address']=item2['地址'];
          newobj['postcode']=item2['邮编'];
          newobj['company']=item2['公司'];
        
          //按行生成对象，并加入数组
          wares.push(newobj);
      });//for -2 end
    //导入偏远邮编
  //   var sheet2 = workbook.Sheets["偏远"];
  //   var data2 = xlsx.utils.sheet_to_json(sheet2)
  //   data2.map((item2)=>{ //for -2 begin
  //      //按行生成对象，并加入数组
  //      isfars.push(item2['邮编']);
  //  });//for -2 end
  // });//for -1 end
  //合并为新数据
  newdata['wares']=wares;
  // newdata['isfars']=isfars;    
    
  // console.log('清理后的数据：'+Buffer.from(JSON.stringify(newdata),'latin1').toString('utf8'));
  //------------------------------------------插入数据库------------------------------------------
  var sql='call p_import_warepostcode(?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,operater_id,JSON.stringify(newdata)];
  console.log("地址邮编上传文件内容："+ opt );
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results[0]};
        console.log('地址邮编上传数据成功。');
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
   
}); 

//导入偏远邮编--------------------------------------------------2024-12-02-----导入偏远邮编--
app.post('/basis_api/upload/file/farpostcode',upload.single('upfile'),function(req,res){
  res.setTimeout(600*1000);
  const {x_id,operater_id}=req.body;
  console.log('偏远邮编文件名:'+filename);
  // res.end();
  //读取刚导入的EXCEL文档，并返回结果
  const workbook=xlsx.readFile('c:/uploads/'+filename);
   console.log('导入偏远邮编表文件名：'+'c:/uploads/'+filename);
   const sheetnames=workbook.SheetNames;
   console.log(JSON.stringify(sheetnames));
   //-------------清理数据-----2024-11-19-------------------------------
   var newdata=[];//全部
     
    //导入偏远邮编
    var sheet = workbook.Sheets["偏远"];
    var data = xlsx.utils.sheet_to_json(sheet)
    data.map((item)=>{ //for -2 begin
       //按行生成对象，并加入数组
        newdata.push(item['邮编']);
    });//for -2 end
   
      
  // console.log('清理后的数据：'+Buffer.from(JSON.stringify(newdata),'latin1').toString('utf8'));
  //------------------------------------------插入数据库------------------------------------------
  var sql='call p_import_farpostcode(?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,operater_id,JSON.stringify(newdata)];
  console.log("偏远邮编上传文件内容："+ opt );
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results[0]};
        console.log('偏远邮编上传数据成功。');
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
});   

///basis_api/miniprogram/login/count/get---------------获取小程序的登录次数---2024-11-14-------------------           
app.post('/basis_api/miniprogram/login/count/get',function(req,res){
  const {px_id,pmodel,type,begindate,enddate}=req.body;
  var sql='call p_mini_getlogincount(?,?,?,?,?)';
  var opt=[px_id,pmodel.toString('utf8'),type,begindate,enddate];
 
console.log('获取小程序登录次数SQL语句1：'+sql);
console.log('获取小程序登录次数OPT参数1：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});
      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results[0]};
        console.log('小程序登录次数据：'+JSON.stringify(j));
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
}); 

///basis_api/business/definevc/:id/:item_id -----------------------在客商管理中按组织ID获取供、客定义---------------
app.get('/basis_api/business/definevc/:org_id/:item_id',function(req,res){
  const org_id=req.params.org_id;
  const item_id=req.params.item_id;

  var sql='select isvendor,iscustomer from v_business_define where org_id=? and item_id=?'
  var opt=[org_id,item_id];
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results[0]};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/grant/getmodel/:sysid -----------------------获取系统ID对应的模块列表------------------------------------
app.get('/basis_api/grant/getmodel/:sysid',function(req,res){
  const sysid=req.params.sysid;
  var sql='select id,name,cname from grant_item where higher_id=0 and sysid=? order by id'
  var opt=[sysid];
 
console.log('SQL语句：'+sql);
console.log('OPT参数：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err)
      res.send({success:false,error:'数据库连接错误：'+err.message});
    conn.query(sql,opt,function(err,results){
        if(err)
           res.send({success:false,error:'查询数据库错误:'+err.message});
        else{
        var j={success:true,data:results};
        res.send(j);  
       }
    });
    conn.release();
 });
}); 

///basis_api/grant/get/grantlist---------------------------获取对应X、组织、角色已有授权信息---------
//s_getGrantDetails({org_id,role_id,model_id})
app.post('/basis_api/grant/get/grantlist',function(req,res){//---1
  //var d2=req.body.paramm;
  const {x_id,org_id,role_id,sys_id,model_id}=req.body;
  
//  res.send({data:'成功更新数据'});
  var sql='call p_getGrantList(?,?,?,?,?)';
  var opt=[x_id,org_id,role_id,sys_id,model_id];                  //---------记住：JSON必须转换为字符串后给MYSQL存储过程。

  console.log('按组织模块获取权限列表SQL：'+sql);  //获取参数，注意前端调用request时，要用data:参数对象
  console.log('按组织模块获取权限列表OPT:'+JSON.stringify(opt));
//先创建连接池，再通过连接执行语句
  pool.getConnection(function(err,conn){   //--2
      if(err)
        console.log('连接池错误');
      else
       console.log('连接数据库成功');
     
  conn.query(sql,opt,function(err,results){   //执行SQL--3
      if(err){
         console.log(err);
       res.end(JSON.stringify({success:false})); //
     }
      else{//--4
      res.end(JSON.stringify({success:true,data:results[0]}));//返回值是，一定要用res.end而不是res.send，因为只能一次性返回数据，且为字符串类型
        console.log('数据库更新成功，恭喜');
      }//--4
 });//--3
  conn.release(); 
} );//连接池结束--2
});
 


//====================================================用户登录及授权=======2024-11-13==========开始==========================================

// const waitTime = (time = 100) => {
//   return new Promise((resolve) => {
//     setTimeout(() => {
//       resolve(true);
//     }, time);
//   });
// };

// async function getFakeCaptcha(req: Request, res: Response) {
//   await waitTime(2000);
//   return res.json('captcha-xxx');
// }

// const { ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION } = process.env;

/**
 * 当前用户的权限，如果为空代表没登录
 * current user access， if is '', user need login
 * 如果是 pro 的预览，默认是有权限的
 */
//  let access = '';
// //let access='admin';
// const getAccess = () => {
//   return access;
// };

///basis_api/currentUser---------------------------获取用户信息--2024-11-13----------------------------

///basis_api/upload/file/price------------------------------------文件上传-基本设置---专用于htoms2-----------------------------
var filename_htoms2='';
const storage_htoms2 = multer.diskStorage({
  destination: function (req, file, cb) {
    const {x_id,source,tdata}=req.body;
    var tdata2=JSON.parse(tdata);
    var dynamicPath='';
    
    if(source=='importdata')
         //导入数据的临时文件夹
         dynamicPath='c:/additions/'.concat(x_id,'/',source,'/',tdata2.data);
    else if(source.indexOf('addition_')!=-1)
        //  通用存放目录
        dynamicPath='c:/additions/'.concat(x_id,'/',source.substring(9),'/',tdata2.code);
     else
        //  样品存放目录，多了一个节点号
        dynamicPath='c:/additions/'.concat(x_id,'/',source,'/',tdata2.code,'/',tdata2.step);
    console.log('设置上传完整路径:'+dynamicPath);
    // 确保目录存在
    fs.mkdir(dynamicPath, { recursive: true }, (err) => {
      if (err) return cb(err, dynamicPath);
          cb(null, dynamicPath);
    });
    
    // cb(null, 'c:/additions') // 文件存储路径
  },
    filename: function (req, file, cb) {
     //  cb(null, file.fieldname) // 文件命名------需组装文件名？？
    // console.log(Buffer.from(file.originalname, 'latin1').toString('utf-8'));
     cb(null,Buffer.from(file.originalname,'latin1').toString('utf-8'));
     filename_htoms2=Buffer.from(file.originalname,'latin1').toString('utf-8');
     console.log('上传的文件名：'+filename_htoms2);
    }
})
const upload_htoms2 = multer({ storage: storage_htoms2 });

//-------------------------------------------------------------------htoms2附件上传=---2024-11-25--------------------------
app.post('/basis_api/upload/file/htoms2',upload_htoms2.single('upfile'),function(req,res){
   const {x_id,source,operater_id,tdata}=req.body;
 //console.log(x);
  // var y=Buffer.from(x.toString());
 //  console.log('2.文件大小 ：'+y.length);
 console.log('文件名上传成功:'+filename_htoms2);
 //将新上传的文件名，添加到参数中
 var tdata2={...JSON.parse(tdata),filename:filename_htoms2};
  //------------------------------------------插入数据库------------------------------------------
  var sql='call s_uploadfile(?,?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,source,operater_id,JSON.stringify(tdata2)];

   console.log('上传函数：'+sql);
   console.log("上传文件参数："+ JSON.stringify(opt));
   
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results[0]};
        console.log('上传后新文件列表：'+JSON.stringify(j));
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
   
}); 


////basis_api/upload/file/htoms2/import------------------------htom2:导入EXCEL数据----2025-06-02--------------------------
app.post('/basis_api/upload/file/htoms2/import',upload.single('upfile'),function(req,res){
  const {x_id,operater_id,source,tdata}=req.body;
//注意：tdata.data为实际对应的导入表格，代替原source

 //console.log(x);
  // var y=Buffer.from(x.toString());
 //  console.log('2.文件大小 ：'+y.length);
 console.log('导入的EXCEL文件名:'+filename);
  // res.end();
  //读取刚导入的EXCEL文档，并返回结果
  const workbook=xlsx.readFile('c:/uploads/'+filename);
   console.log('文件全路径名：'+'c:/uploads/'+filename);
   const sheetnames=workbook.SheetNames;
   console.log('工作簿：'+JSON.stringify(sheetnames));
   //-------------清理数据-----2025-06-02-----------------------------------
   var newdata=[];//全部sheet的总表
   sheetnames.map((item)=>{ //for -1 begin --只有一个sheet1,循环备用。
       var sheet = workbook.Sheets[item];
       var data = xlsx.utils.sheet_to_json(sheet)
        //各导入模板分别取字段,tdata
       if(tdata=='materialcodes')
          data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['custom_code']=item2['店铺编码']
               newobj['material_code']=item2['商品SKU']
               newobj['custom_sku']=item2['店铺SKU'];
               newobj['fn_sku']=item2['FNSKU'];
               newobj['ansi_sku']=item2['ANSISKU'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });//for -2 end
      else if(tdata=='sale_order')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['custom_code']=item2['店铺编码'];
               newobj['deliverdate']=item2['预计交货日期'];
               newobj['fn_sku']=item2['FNSKU'];
               newobj['quantity']=item2['QTY'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
          });//for -2 end
      else if(tdata=='deliver_order')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['custom_code']=item2['店铺编码'];
               newobj['fn_sku']=item2['FNSKU'];
               newobj['quantity']=item2['QTY'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
       else if(tdata=='vendor_priceschedule')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['vendor_code']=item2['供应商编码'];
               newobj['material_code']=item2['商品SKU'];
               newobj['price']=item2['含税单价'];
               newobj['taxrate']=item2['税率'];
               newobj['isdefault']=item2['是否默认'];
               newobj['begindate']=item2['生效日期'];
               newobj['enddate']=item2['截止日期'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
      else if(tdata=='base_warehouse_pos')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['warehouse_code']=item2['仓库编码'];
               newobj['whposition_code']=item2['库位编码'];
               newobj['whposition_name']=item2['库位名称'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
      else if(tdata=='base_person')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['用户编码'];
               newobj['name']=item2['姓名'];
               newobj['sex']=item2['性别'];
               newobj['org_code']=item2['部门编码'];
               newobj['isuser']=item2['是否用户'];
               newobj['isbusiness']=item2['是否业务员'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
       else if(tdata=='material_category')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['分类编码'];
               newobj['name']=item2['分类名称'];
               newobj['layer']=item2['层级'];
               newobj['higher_code']=item2['上级分类编码'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
       else if(tdata=='material')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['SKU编码'];
               newobj['name']=item2['名称'];
               newobj['invstd']=item2['规格'];
               newobj['unit_name']=item2['单位'];
               newobj['default_warehouse_code']=item2['默认仓库编码'];
               newobj['defalut_whposition_code']=item2['默认库位码'];
               newobj['category_name']=item2['商品类别'];
               newobj['default_type']=item2['默认类型'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
       else if(tdata=='person')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['用户编码'];
               newobj['name']=item2['姓名'];
               newobj['sex']=item2['性别'];
               newobj['dep_name']=item2['部门编码'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
      else if(tdata=='base_role')
           data.map((item2)=>{ //for -2 begin
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['角色编码'];
               newobj['name']=item2['名称'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
      else if(tdata=='base_custom')
           data.map((item2)=>{ //for -2 begin  分类编码	店铺编码	店铺名称	默认联系人
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['category_code']=item2['分类编码'];
               newobj['code']=item2['店铺编码'];
               newobj['name']=item2['店铺名称'];
               newobj['business_name']=item2['默认联系人'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
      // 编码	名称	简称	联系人	联系电话	地址
     else if(tdata=='base_vendor')
           data.map((item2)=>{ //for -2 begin  分类编码	店铺编码	店铺名称	默认联系人
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['编码'];
               newobj['name']=item2['名称'];
               newobj['sname']=item2['简称'];
               newobj['connector']=item2['联系人'];
               newobj['telephone']=item2['联系电话'];
               newobj['address']=item2['地址'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
       else if(tdata=='craft_card')
           data.map((item2)=>{ //for -2 begin  分类编码	店铺编码	店铺名称	默认联系人
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['工序编码'];
               newobj['name']=item2['工序名称'];
               newobj['workcenter_name']=item2['默认生产中心'];
               newobj['workgroup_name']=item2['默认生产组'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      }); 
      else if(tdata=='craft_route')
           data.map((item2)=>{ //for -2 begin  分类编码	店铺编码	店铺名称	默认联系人
               var newobj={};//对单行价格明细遍历[{weight:XX,price:xx,ware_code:XX}...]
               newobj['code']=item2['工艺编码'];
               newobj['name']=item2['工艺名称'];
               newobj['version']=item2['版本号'];
               newobj['card_code']=item2['工序编码'];
               newobj['sno']=item2['顺序'];
               newobj['isend']=item2['是否末工序'];
               //按行生成对象，并加入数组
               newdata.push(newobj);
      });
   });//for -1 end
    // console.log("导入文件明细内容："+ JSON.stringify(newdata) );
  // console.log('清理后的数据：'+Buffer.from(JSON.stringify(newdata),'latin1').toString('utf8'));
  //------------------------------------------插入数据库------------------------------------------
  var sql='call p_all_importdata(?,?,?,?)';
 //  var opt=[x_id,operater_id,begindate,chanelcategory_id,JSON.stringify(newdata)]; //px_id,poperater_id,tdata
   var opt=[x_id,tdata,operater_id,JSON.stringify(newdata)];
   console.log("导入文件明细内容："+ opt );
   console.log(tdata);
   pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});

      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString());
            }
        else{
        var j={success:true,data:results[0]};
        console.log('导入数据成功。');
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
   
}); 
 

// /basis_api/quoteprice/get--------------------------------获取报价明细内容--2025-01-27----------------------------
app.post('/basis_api/quoteprice/get',function(req,res){
  const {ptype,mid}=req.body;
  var sql='call s_getquotepricedetail(?,?)';
  var opt=[ptype,mid];
 
console.log('获取报价单内容SQL语句1：'+sql);
console.log('获取报价单内容OPT参数1：'+JSON.stringify(opt));

 pool.getConnection(function(err,conn){
    if(err){// if-begin
      res.send({success:false,error:'数据库连接错误：'+err.message});
      console.log('数据库连接错误：'+err.toString());
    }else{
       conn.query(sql,opt,function(err,results){
        if(err){
           res.send({success:false,error:'查询数据库错误:'+err.message});
           console.log('数据库执行错误：'+err.toString())
            }
        else{
        var j={success:true,data:results};
        console.log('小程序登录次数据：'+JSON.stringify(j));
        res.send(j);  
       }
    });
  }// if-end
    conn.release();
    return;
 });
}); 





























//------------------------------------------------服务器启用----和---FORM组件数据源-------------------------------
//创建服务器，回调函数中不带参数？
var server = app.listen(8081, function () {
  console.log("服务器成功启动！！")
})


///basis_api/selection/:x_id/:source/:id组织--下拉框数据源--注意：source为数据库表名
app.get('/basis_api/selection/:x_id/:source/:id',function(req,res){
  const x_id=req.params.x_id;
  const source=req.params.source;
  const id=req.params.id;
  const code=req.params.code;//仅用于特殊的表，如计量单位
  
  var sql='select id,code,name from '+source +' where 1=1 ';
  var opt=[];
  
  //传入为-1时，代表全部/附加：传入0时，用于base_organization中取组织类型为集团和公司，且未停用的
  if(id!=-1&&id!=0){  
     sql=sql+' and id=?';
     opt=[id];
  }

//传入0时，穿梭框，用于base_organization中取组织类型为集团和公司，且未停用的
  if(source==='base_organization'&&id==='0')//注意：默认传入的是字符类型，所以用===号时要加引号；否则用==号
  {
    sql=sql+' and x_id=? and  org_type in (1,2) and status=1' ;
    opt=[x_id];
  }

  if(source==='base_person'&&id==='0')//传入0时，穿梭框，用于base_person中获取用户信息，且未停用//注意：用===号时要加''号
  {
    sql=sql+'and x_id=?  and isuser=1 and status=1' ;
    opt=[x_id];
  }

  if(source==='author_area')
  {
    sql='select * from '+source;  //此处返回3列，因此直接用*
  }
//单位特殊处理，因code为通用
  if(source==='unit'){
    sql='select code,name from unit '.concat((code==='999'?'':' where code=?'),' order by code');
    opt=[code];
  }

  console.log('SQL语句：'+sql);
  console.log('传入的OPT：'+JSON.stringify(opt));

  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
          else{
         var j={success:true,data:results};
         console.log('穿梭框值：'+JSON.stringify(j));
         //获取数据为数组形态，应该转换为下拉框键值对
         res.send(j);  
        }
     });
     conn.release();
  });
}); 


//通用的SELECTION数据源组件options--------------------------------可接收参数不限POST----------------------------------
app.post('/basis_api/selection/comm',function(req,res){
  const x_id=req.body.x_id;   
  const source=req.body.source;  //来源表格或视图名
  const id=req.body.id;
  const code=req.body.code;//仅用于特殊的表，如计量单位
  const type=req.body.type;//用于特殊场合，如只显示符合某些条件的情况

  //最初没有定义sql和opt,导致数据混乱，晕菜了好久。。。加上以下两个var语句就正常了。
  var sql='';
  var opt=[];

  //通用取数
    sql='select id,code,(case status when 1 then name else concat(name,"(停)") end) as name from '+source+' where  x_id=? order by id';
    opt=[x_id];
  

//单位特殊处理，因code为通用
  if(source==='unit'){
    sql='select id,code,name from unit '.concat((code==='999'?'':' where code=?'),' order by code');
    opt=[code];
  };

  //用户,注意是返回id
 if(source==='base_person'){
  sql='select id,code,(case status when 1 then name else concat(name,"(停)") end) as name from  base_person where   x_id=? order by id';
  opt=[x_id];
 };

 //组织,注意是返回id
 if(source==='base_organization'&&type==='businessallocateorg'){
  sql='select id,code,(case status when 1 then name else concat(name,"(停)") end) as name  from  base_organization where org_type in(1,2)   and  x_id=? ';
  sql=sql+' and id in(select org_id from allocate where item_type=1 and item_id=? and status=1) order by id';
  opt=[x_id,id];
 };

  //经营类目,注意是返回id------统一返回，不区分x_id
  if(source=='base_industry'){
    sql='select id,code,(case status when 1 then name else concat(name,"(停)") end) as name from  base_industry where  isend=1 order by id';
    // opt=[x_id];
    opt=[];
   };

     //岗位,注意是返回id
  if(source=='base_job'){
    sql='select id,code,(case status when 1 then name else concat(name,"(停)") end) as name from  base_job where     x_id=? order by id';
    opt=[x_id];
   };

  console.log('SQL语句：'+sql);
  console.log('传入的OPT：'+JSON.stringify(opt));

  pool.getConnection(function(err,conn){
     if(err)
       res.send({success:false,error:'数据库连接错误：'+err.message});
     conn.query(sql,opt,function(err,results){
         if(err)
            res.send({success:false,error:'查询数据库错误:'+err.message});
          else{
         var j={success:true,data:results};
         console.log('下拉选项值：'+JSON.stringify(j));
         //获取数据为数组形态，应该转换为下拉框键值对
         res.send(j);  
        }
     });
     conn.release();
  });
}); 




// 以下为用户登录及权限控制==============2025-02-14========================================================
// 设置登录的账户及密码等变量，在登录时更新；并在获取用户数据时作为参数。
var login_xcode;
var login_usercode;
var login_password;
var login_type;
var login_mobile;
var login_captcha;

const waitTime = (time = 100) => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(true);
    }, time);
  });
};

async function getFakeCaptcha(req, res) {
  await waitTime(2000);
  return res.json('captcha-xxx');
}

var access =  '11';

const getAccess = () => {
  return access;
};

// 获取登录用户详细信息   2025-02-14
app.post('/basis_api/api/currentUser',function(req,res){    //带参数为组织编号
  if (!getAccess()) {
    res.status(401).send({
      data: {
        isLogin: false,
      },
      errorCode: '401',
      errorMessage: '请先登录！',
      success: true,
    });
    return;
  }

//读取用户信息
  // const {x_id,usercode,password}=req.body;
  //--注意：添加查找权限的功能，下面语句改成存储过程：验证用户是否存在，同时返回权限。
  var sql='call p_getcurrentuser(?,?,?,?,?,?)';
  //  login_xcode,login_usercode,login_password,login_type,login_mobile,login_captcha
  // 参数来自于登录时赋予的变量
  var opt=[login_xcode,login_usercode,login_password,login_type,login_mobile,login_captcha];
   
  console.log('读取用户信息SQL:'+sql);
  console.log('读取用户信息OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        res.status(401).send({
          data: {
            isLogin: false,
          },
          errorCode: '401',
          errorMessage: '登录错误，请检查账号和密码。'+err,
          success: true,
        });
        console.log('读取用户信息错误+++：'+err);
        return;
      }
        // var j={success:true,data:results};
        
        // name,avatar,userid,email,signature,title,group,tags,access,geopgraphic,
        // address,mobilephone,phone,hasRoute,hasOperate
        var userinfo=results[0][0];
        //var grantinfo=results[1][0];
        //var operateinfo=results[2][0];
        // console.log(JSON.stringify(userinfo));
        // console.log(JSON.stringify(grantinfo));

      //组装用户信息---2
      var data;
       if(userinfo
       //&&grantinfo&&operateinfo
       ){
        data={ x_id:userinfo.x_id,  
                  name:userinfo.name,
                  code:userinfo.code,
                  password:userinfo.password,
                  sex:userinfo.sex,
                   avatar:userinfo.avatar,
                   userid:userinfo.id,
                   email:userinfo.email,
                   signature:userinfo.signature,
                   title:userinfo.title,
                   tags:userinfo.tags,
                   access:getAccess(),
                   address:userinfo.address,
                   mobilephone:userinfo.mobilephone,
                   phone:userinfo.phone,
                   //hasRoute:grantinfo.routenames?grantinfo.routenames:[],
                   //hasOperate:operateinfo.operatenames?operateinfo.operatenames:[],
                   };
                   res.send({success:true,data});
                  
                  
         //if (userinfo) {
         //     console.log('恭喜！用户登录成功！');
         //     res.send({
         //       status: 'ok',
         //       type:'user',
         //       currentAuthority: 'user',
         //       data,
         //     });
         //     access = 'user';
              //控制台输出信息
         //     console.log('用户登录信息：'+JSON.stringify(data));
         //     return;
         //   }
            } 
        else{
          //  data={x_id:null,};
            data=undefined;
            res.send({success:false,data});
           }
      console.log('刷新获取的用户和权限信息：'+JSON.stringify({success:true,data}));
       });

   conn.release();
   return;
});
 });


 
  // GET POST 可省略  name,avatar,userid,email,signature,title,group,tags,access,geopgraphic,address,mobilephone,phone
//   'GET /api/users': [
//     {
//       key: '1',
//       name: 'John Brown',
//       age: 32,
//       address: 'New York No. 1 Lake Park',
//     },
//     {
//       key: '2',
//       name: 'Jim Green',
//       age: 42,
//       address: 'London No. 1 Lake Park',
//     },
//     {
//       key: '3',
//       name: 'Joe Black',
//       age: 32,
//       address: 'Sidney No. 1 Lake Park',
//     },
//   ],

// 用户登录验证  2025-02-14
app.post('/basis_api/api/login/account',function(req,res){   
  
//读取用户信息
  const {x_code,usercode,password,type,mobile,captcha}=req.body;
  //--注意：添加查找权限的功能，下面语句改成存储过程：验证用户是否存在，同时返回权限。
  //type:account或mobile表示登录方式
  var sql='call p_getcurrentuser(?,?,?,?,?,?)';
  //  login_xcode,login_usercode,login_password,login_type,login_mobile,login_captcha
  // 参数来自于登录时赋予的变量
  var opt=[x_code,usercode,password,type,mobile,captcha];
  // 赋值变量，用于用户信息调用
  login_xcode=x_code;
  login_usercode=usercode;
  login_password=password;
  login_type=type;
  login_mobile=mobile;
  login_captcha=captcha;
   
  console.log('用户登录信息SQL:'+sql);
  console.log('用户登录信息OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
        res.status(401).send({
          data: {
            isLogin: false,
          },
          errorCode: '401',
          errorMessage: '请输入账号和密码。'+err,
          success: true,
        });
        return;
      }

      var userinfo=results[0][0];
      //var grantinfo=results[1][0];
      //var operateinfo=results[2][0];
      // console.log(JSON.stringify(userinfo));
      // console.log(JSON.stringify(grantinfo));

    //组装用户信息
      var data;
      if(userinfo
      //&&grantinfo&&operateinfo
      ){
      data={ 
                 x_id:userinfo.x_id,  
                 name:userinfo.name,
                 code:userinfo.code,
                 password:userinfo.password,
                 sex:userinfo.sex,
                 avatar:userinfo.avatar,
                 userid:userinfo.id,
                 email:userinfo.email,
                 signature:userinfo.signature,
                 title:userinfo.title,
                 tags:userinfo.tags,
                 access:getAccess(),
                 address:userinfo.address,
                 mobilephone:userinfo.mobilephone,
                 phone:userinfo.phone,
                 //hasRoute:grantinfo.routenames?grantinfo.routenames:[],
                 //hasOperate:operateinfo.operatenames?operateinfo.operatenames:[],
                 };
        
      if (userinfo) {
              console.log('恭喜！用户登录成功！');
              res.send({
                status: 'ok',
                type:'user',
                currentAuthority: 'user',
                data,
              });
              access = 'user';
              //控制台输出信息
              console.log('用户登录信息：'+JSON.stringify(data));
              return;
            }
       
       
       }else{
          //  data={x_id:null,};
            data=undefined;
            res.send({success:false,data});
           }
      console.log('刷新获取的用户和权限信息：'+JSON.stringify({success:true,data}));
       });

   conn.release();
   return;
});
 });

//   'POST /api/login/account': async (req: Request, res: Response) => {
//     const { password, username, type } = req.body;
//     await waitTime(2000);
//     if (password === 'ant.design' && username === 'admin') {
//       res.send({
//         status: 'ok',
//         type,
//         currentAuthority: 'admin',
//       });
//       access = 'admin';
//       return;
//     }
//     if (password === 'ant.design' && username === 'user') {
//       res.send({
//         status: 'ok',
//         type,
//         currentAuthority: 'user',
//       });
//       access = 'user';
//       return;
//     }
//     if (type === 'mobile') {
//       res.send({
//         status: 'ok',
//         type,
//         currentAuthority: 'admin',
//       });
//       access = 'admin';
//       return;
//     }

//     res.send({
//       status: 'error',
//       type,
//       currentAuthority: 'guest',
//     });
//     access = 'guest';
//   },

app.post('/basis_api/api/login/outLogin',function(req,res){ 
      access = '';
      res.send({ data: {}, success: true });

});
//   'POST /api/login/outLogin': (req: Request, res: Response) => {
//     access = '';
//     res.send({ data: {}, success: true });
//   },

// //注册新用户，直接在系统内基础设置里完成
// app.post('/basis_api/api/login/outLogin',function(req,res){ 
//   access = '';
//   res.send({ data: {}, success: true });

// });

//   'POST /api/register': (req: Request, res: Response) => {
//     res.send({ status: 'ok', currentAuthority: 'user', success: true });
//   },

app.post('/basis_api/api/500',function(req,res){ 
  res.status(500).send({
          timestamp: 1513932555104,
          status: 500,
          error: 'error',
          message: 'error',
          path: '/base/category/list',
        });

});
//   'GET /api/500': (req: Request, res: Response) => {
//     res.status(500).send({
//       timestamp: 1513932555104,
//       status: 500,
//       error: 'error',
//       message: 'error',
//       path: '/base/category/list',
//     });
//   },
app.post('/basis_api/api/404',function(req,res){ 
  res.status(500).send({
          timestamp: 1513932643431,
          status: 404,
          error: 'not found',
          message: 'error',
          path: '/base/category/list',
        });

});
//   'GET /api/404': (req: Request, res: Response) => {
//     res.status(404).send({
//       timestamp: 1513932643431,
//       status: 404,
//       error: 'Not Found',
//       message: 'No message available',
//       path: '/base/category/list/2121212',
//     });
//   },

app.post('/basis_api/api/403',function(req,res){ 
  res.status(500).send({
          timestamp: 1513932643431,
          status: 403,
          error: 'Forbidden',
          message: 'error',
          path: '/base/category/list',
        });

});

//   'GET /api/403': (req: Request, res: Response) => {
//     res.status(403).send({
//       timestamp: 1513932555104,
//       status: 403,
//       error: 'Forbidden',
//       message: 'Forbidden',
//       path: '/base/category/list',
//     });
//   },
app.post('/basis_api/api/401',function(req,res){ 
  res.status(500).send({
          timestamp: 1513932643431,
          status: 401,
          error: 'Unauthorized',
          message: 'error',
          path: '/base/category/list',
        });

});

//   'GET /api/401': (req: Request, res: Response) => {
//     res.status(401).send({
//       timestamp: 1513932555104,
//       status: 401,
//       error: 'Unauthorized',
//       message: 'Unauthorized',
//       path: '/base/category/list',
//     });
//   },
app.post('/basis_api/api/login/captcha',function(req,res){ 
     getFakeCaptcha;

});
//   'GET  /api/login/captcha': getFakeCaptcha,
// };


//====================================================用户登录及授权=======2024-11-13========结束============================================

// 供应链平台小程序  以下=============================2025-02-24==============================================
// /basis_api/miniprogram/searchitembytag  商品列表： 按关键字查询商品明细 
app.post('/basis_api/miniprogram/getcommoninfo',function(req,res){    // 
  const {x_id,source,tdata}=req.body;
  var sql='call p_mini_getcommoninfo(?,?,?)';
  var opt=[x_id,source,JSON.stringify(tdata)];
  
  console.log('查询商品SQL:'+sql);
  console.log('查询商品OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
          res.send({success:false,error:err});
      }else{
      var j={success:true,data:results};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
      }
       });
   conn.release();
});
 });

 ///basis_api/miniprogram/updatecommoninfo------------------更新小程序-2025-03-04-----------------------------
 app.post('/basis_api/miniprogram/updatecommoninfo',function(req,res){    // 
  const {x_id,type,source,operater_id,tdata}=req.body;
  var sql='call p_mini_updatecommoninfo(?,?,?,?,?)';
  var opt=[x_id,source,type,operater_id,JSON.stringify(tdata)];
  
  console.log('加入采购车SQL:'+sql);
  console.log('加入采购车OPT:'+JSON.stringify(opt));
  
  pool.getConnection(function(err,conn){
       if(err)
          console.log('数据库连接失败');
      else 
          console.log('数据库连接成功');
     conn.query(sql,opt,function(err,results){
      if(err){
          res.send({success:false,error:err});
      }else{
      var j={success:true};
      //console.log(source+'获取SELECT下拉数据：'+JSON.stringify(d));
      res.send(j);
      }
       });
   conn.release();
});
 });
